Típicamente en F # en lugar de utilizar los flujos de trabajo genéricos se define el flujo de trabajo a mano, o utilizar uno que está listo a disposición como en su caso async
y maybe
pero si desea utilizarlos en combinación tendrá que codificar una combinación específica de flujo de trabajo a mano.
Alternativamente, puede utilizar F#+ que es un proyecto que proporciona flujos de trabajo genéricos de mónadas, en ese caso se deriva automáticamente para usted, aquí hay un ejemplo de trabajo, utilizando el flujo de trabajo y luego usando OptionT
que es un transformador mónada:
#nowarn "3186"
#r @"FSharpPlus.dll"
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
la primera función tiene que ser 'levantado' en la otra mónada, ya que sólo se ocupa de Async
(no con Option
), el segundo se ocupa de funciones con tanto por lo que sólo necesita ser 'lleno' en nuestro OptionT
DU.
Como puede ver, ambos flujos de trabajo se derivan automáticamente, el que tenía (el flujo de trabajo asincrónico) y el que desea.
Para obtener más información sobre este enfoque, lea acerca de Monad Transformers.
Creo que estás pidiendo lo que Haskell llama "transformadores de mónada", en cuyo caso la respuesta corta es "no". No hay una forma genérica de combinarlos, desafortunadamente. En Haskell hay una versión de transformador de cada mónada estándar que luego puede injertar en otras, pero no estoy seguro de que sea posible definirlas en el sistema de tipos de F # ... –
Puede que le interese una característica propuesta aprobada llamada [coincidencia !] (https://github.com/fsharp/fslang-suggestions/issues/572) (como en "match-bang"): es un "let!" seguido de un "partido". He querido algo de lo que estás hablando hace un tiempo, y he estado trabajando para que se implemente en F # – Jwosty