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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions