3

当我尝试组合这两个转换器时 fsi 阻塞,没有任何警告或错误消息。

open FSharpPlus
open FSharpPlus.Data

type MyError = | Err of string

let f : WriterT<ResultT<Async<Result<_, MyError>>>> = monad {
    do! liftAsync <| Async.Sleep 30
    do! tell ["abc"]
    let! r0 = lift<| ResultT.hoist (Ok 25)
    return r0 + 5
    }

let g = monad {
    let! r1 = f
    do! tell ["def"]
    do! liftAsync <| Async.Sleep 50
    let! r2 = lift<| ResultT.hoist (Ok 2)
    return r1 + r2
    }

let runStackT stack = stack |> WriterT.run |> ResultT.run |> Async.RunSynchronously

#time "on"
let finalResult = runStackT g
#time "off"

有什么问题以及如何使此代码工作?

4

1 回答 1

0

如评论中所述,这是一个 F# 错误。

您的代码是正确的,即使不是,也没有理由让 F# 编译器挂起。

如果您更改这些行,我找到了一种解决方法:

...
let g: WriterT<ResultT<Async<Result<_, MyError>>>> = monad {
    let! r1 = f
    let! _ = tell ["def"]
    let! _ = liftAsync <| Async.Sleep 50
    let! r2 = WriterT.Lift <| ResultT.hoist (Ok 2)
    ...

它会起作用的。

请注意,将 a 更改do!为 alet! _ =是我经常用来改进类型推断的技巧。

于 2019-12-04T21:55:32.367 回答