Skip to content

Option<ISeq<T>>をクエリ式で扱えるようにする? #7

@bleis-tift

Description

@bleis-tift

SeqExt.QueryExpr.SeqOption名前空間に下のような関数を追加する。

public static Option<ISeq<V>> SelectMany<T, U, V>(
    this ISeq<Option<T>> self, Func<T, Option<U>> f, Func<T, U, V> g)
{
    var res = new System.Collections.Generic.List<V>();
    foreach (var opt in self)
    {
        if (opt.IsNone)
            return Option.None;
        var t = LangExt.Unsafe.Option.GetValue(opt);
        var v = f(t).Bind(u => Option.Some(g(t, u)));
        if (v.IsNone)
            return Option.None;
        res.Add(LangExt.Unsafe.Option.GetValue(v));
    }
    return Option.Some(res.ToSeq());
}

public static Option<ISeq<V>> SelectMany<T, U, V>(
    this Option<ISeq<T>> self, Func<T, Option<U>> f, Func<T, U, V> g)
{
    if (self.IsNone)
        return Option.None;
    var xs = LangExt.Unsafe.Option.GetValue(self);
    var res = new System.Collections.Generic.List<V>();
    foreach (var x in xs)
    {
        var t = x;
        var v = f(t).Bind(u => Option.Some(g(t, u)));
        if (v.IsNone)
            return Option.None;
        res.Add(LangExt.Unsafe.Option.GetValue(v));
    }
    return Option.Some(res.ToSeq());
}

ネストするたびにSystem.Collections.Generic.List[T]を作るのは微妙。
→専用のシーケンス、もしくはIE[T]を実装するのもアリ。意図しない呼び出し(上の例では、上のバージョンのSelectManyを呼び出していないのに、下のバージョンのSelectManyが呼び出されてしまう恐れがある)も防げそうだし。

Resultや、逆バージョンも用意する?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions