1

多分ワークフローで関数をチェーンできるようにしながら、状態を渡す必要があります。2 つのワークフローが同じコンテキストを共有する方法はありますか? いいえの場合、それを行う方法は何ですか?

アップデート:

さて、データベースで作成しようとしているエンティティの利用可能な ID のセグメントを表す状態があります。そのため、ID を取得したら、その状態を次に使用可能な ID を使用して新しい状態に変換し、誰もそれを再び使用できないように破棄する必要があります。慣用的になるために状態を変更したくありません。State モナドは、変換を隠して状態を渡すため、進むべき道のように見えます。状態ワークフローが整ったら、どこでも使用する Maybe ワークフローを使用できません。

4

3 に答える 3

2

F# では、モナド トランスフォーマーや類似の手法を使用して Haskell で行うように、異なる種類の計算式を簡単に混在させることはできません。ただし、次のように、状態スレッドとオプションの値を埋め込んで、独自の Monad を構築することもできます。

type StateMaybe<'T> = 
    MyState -> option<'T> * MyState

// Runs the computation given an initial value and ignores the state result.
let evalState (sm: StateMaybe<'T>) = sm >> fst

// Computation expression for SateMaybe monad.
type StateMaybeBuilder() =
    member this.Return<'T> (x: 'T) : StateMaybe<'T> = fun s -> (Some x, s)
    member this.Bind(sm: StateMaybe<'T>, f: 'T -> StateMaybe<'S>) = fun s ->
        let mx,s' = sm s
        match mx with
        | Some x    -> f x s'
        | None      -> (None, s)

// Computation expression builder.
let maybeState = new StateMaybeBuilder()

// Lifts an optional value to a StateMaybe.
let liftOption<'T> (x: Option<'T>) : StateMaybe<'T> = fun s -> (x,s)

// Gets the current state.
let get : StateMaybe<MyState> = fun s -> (Some s,s)

// Puts a new state.
let put (x: MyState) : StateMaybe<unit> = fun _ -> (Some (), x)

計算例を次に示します。

// Stateful computation
let computation =
    maybeState {
        let! x = get
        let! y = liftOption (Some 10)
        do! put (x + y)
        let! x = get
        return x
    }

printfn "Result: %A" (evalState computation 1)

StateMaybe状態コンポーネントの型をジェネリックにすることで、さらに一般化できます。

于 2013-10-02T17:55:34.330 に答える
1

他の人はすでにあなたの質問に直接答えています。ただし、質問が述べられている方法は、F# の観点からはあまり慣用的ではない解決策につながると思います-コードに取り組んでいるのがあなただけである限り、これはうまくいくかもしれませんが、そうしないことをお勧めします.

詳細を追加しても、質問はまだかなり一般的ですが、ここに 2 つの提案があります。

  • F# で合理的に使用される可変状態に問題はありません。たとえば、ID を生成して渡す関数を作成しても問題ありません。

    let createGenerator() = 
      let currentID = ref 0
      (fun () -> incr currentID; !currentID)
    
  • エンティティの作成中に ID を生成する必要は本当にありますか? ID なしでエンティティのリストを生成し、ID のSeq.zipリストを持つエンティティの最終リストを圧縮するために使用できるように思えます。

  • 多分計算に関しては、通常の有効な状態を処理するために使用していますか、それとも例外的な状態を処理するために使用していますか? (最初の方法のように聞こえますが、これは正しい方法ですが、本当に例外的な状態を処理する必要がある場合は、通常の .NET 例外を使用することをお勧めします)。

于 2013-10-03T16:01:36.730 に答える