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

时间:2015-01-28 17:39:04

标签: haskell asynchronous f# monad-transformers state-monad

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

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

  • 将状态保持在可变变量中并使用async& MailboxProcessor接收修改状态的异步请求
  • 使用状态计算表达式但无法处理用户输入。

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

1 个答案:

答案 0 :(得分:4)

基本上有两种组合monad的方法:使用monad变换器或手工创建一个自定义monad,它结合了两个monad。

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

这是从Haskell翻译的一个例子:

#r @"FSharpPlus.dll"

open FSharpPlus

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

另请参阅thisthis相关问题。