3

私は現在 F# を学んでいて、いくつかのつまずきにぶつかっています。その多くは、機能的に考えることを学ぶことだと思います。

現時点で私が学んでいることの 1 つは計算式であり、追跡状態を処理する計算式を定義できるようにしたいと考えています。

let myOptions = optionListBuilder {
    let! opt1 = {name="a";value=10}
    let! opt2 = {name="b";value=12}
}

myOptionsそれをにできるようにしたいOption<'T> listので、各let!バインド操作により、ビルダーは定義されたオプションを効果的に「追跡」します。

変更可能な状態を使用してそれを行う必要はありません。たとえば、ビルダーによってリストが維持され、bind呼び出しごとに更新されます。

これを可能にする方法はありますか?


更新:結果のOption<'T> list型は代表的なものにすぎません。実際にはOptionGroup<'T>、リストといくつかの追加情報を含む型がある可能性が高いため、ダニエルが以下で述べたように、単純なリストにリスト内包表記を使用できます。

4

3 に答える 3

3

解決

mydogisbox が提供するベースラインの StringBuilder CE ビルダーを使用して、魅力的に機能する次のソリューションを作成することができました。

type Option<'T> = {Name:string;Item:'T}

type OptionBuilderUnion<'T> =
    | OptionItems of Option<'T> list
    | OptionItem of Option<'T>

type OptionBuilder () =
    member this.Yield (opt: Option<'t>) = OptionItem(opt)
    member this.Yield (tup: string * 't) = OptionItem({Name=fst tup;Item=snd tup})
    member this.Combine (f,g) = 
        OptionItems(
            match f,g with
            | OptionItem(F), OptionItem(G) -> [F;G]
            | OptionItems(F), OptionItem(G) -> G :: F
            | OptionItem(F), OptionItems(G) -> F :: G
            | OptionItems(F), OptionItems(G) -> F @ G
        )
    member this.Delay f = f()
    member this.Run (f) = match f with |OptionItems items -> items |OptionItem item -> [item]

let options = OptionBuilder()

let opts = options {
        yield ("a",12)
        yield ("b",10)
        yield {Name = "k"; Item = 20}
    }

opts |> Dump
于 2014-12-12T17:48:44.943 に答える