通常、F#では、一般的なワークフローを使用する代わりに、ワークフローを手動で定義するか、ケースのようにすぐに使用できるワークフローを使用しますが、それらasync
をmaybe
組み合わせて使用する場合は、特定のワークフローの組み合わせを手動でコーディングする必要があります。
または、モナドの一般的なワークフローを提供するプロジェクトであるF#+を使用することもできます。その場合、自動的に派生します。ワークフローを使用OptionT
して、モナド変換子を使用する実際の例を次に示します。
#r "nuget: FSharpPlus, 1.2"
open FSharpPlus
open FSharpPlus.Data
let doAsyncThing = async {return System.DateTime.Now}
let doNextAsyncThing (x:System.DateTime) = async {
let m = x.Millisecond
return (if m < 500 then Some m else None)}
let f x = 2 * x
// then you can use Async<_> (same as your code)
let run = monad {
let! x = doAsyncThing
let! y = doNextAsyncThing x
match y with
| None -> return None
| Some z -> return Some <| f z}
let res = Async.RunSynchronously run
// or you can use OptionT<Async<_>> (monad transformer)
let run' = monad {
let! x = lift doAsyncThing
let! y = OptionT (doNextAsyncThing x)
return f y}
let res' = run' |> OptionT.run |> Async.RunSynchronously
最初の関数は他のモナドに「リフト」する必要があります。これは、を処理するだけでAsync
(を処理しないため)、2番目の関数は両方を処理するため、 DUOption
に「パック」するだけで済みます。OptionT
ご覧のとおり、両方のワークフローが自動的に導出されます。つまり、使用していたワークフロー(非同期ワークフロー)と必要なワークフローです。
このアプローチの詳細については、モナド変換子についてお読みください。