如何使用状态 monad 通过异步请求更新状态?
How to update the state with async requests using the state monad?
我正在使用 F# 开发一个应用程序,我想知道我是否可以 a) 将状态保持在状态计算表达式下(使用 FSharpx 的实现)和 b) 能够异步修改状态(处理用户的输入)。
我相信我知道如何分别处理每个问题;或者:
- 将状态保存在可变变量中,并使用 async & MailboxProcessor 接收异步请求来修改状态
- 使用状态计算表达式但无法处理用户输入。
如何在 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 相关问题。
我正在使用 F# 开发一个应用程序,我想知道我是否可以 a) 将状态保持在状态计算表达式下(使用 FSharpx 的实现)和 b) 能够异步修改状态(处理用户的输入)。
我相信我知道如何分别处理每个问题;或者:
- 将状态保存在可变变量中,并使用 async & MailboxProcessor 接收异步请求来修改状态
- 使用状态计算表达式但无法处理用户输入。
如何在 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 相关问题。