如何使用状态 monad 通过异步请求更新状态?

How to update the state with async requests using the state monad?

我正在使用 F# 开发一个应用程序,我想知道我是否可以 a) 将状态保持在状态计算表达式下(使用 FSharpx 的实现)和 b) 能够异步修改状态(处理用户的输入)。

我相信我知道如何分别处理每个问题;或者:

如何在 FSharp 或 Haskell 中同时使用状态和异步计算表达式?

基本上有两种组合 monad 的方法:使用 monad 转换器或手动创建一个自定义 monad 来组合两个 monad。

由于 F# 中没有本机类型 类,您通常会采用后一种解决方案,但您可以使用 F#+ 组合 Async 和 State a-la Haskell 和得到想要的计算表达式。

这是一个翻译自 Haskell 的示例:

#r @"FSharpPlus.dll"

open FSharpPlus
open FSharpPlus.Data

let print x = async {printfn "%A" x}

#nowarn "0025" // Incomplete pattern match, list is assumed not to be empty.
let code  =
    let inline io (x: Async<_>)  : StateT<_,Async<_>> = liftAsync x
    let pop  = monad {
        let! (x::xs) = get
        do! put xs
        return x}
    monad {
        let! x = pop
        do! io <| print x
        let! y = pop
        do! io <| print y
        return () }

let main = StateT.run code [1..10] >>= fun _ -> result ()

// try Async.RunSynchronously main

另见 this and this 相关问题。