gpt4 book ai didi

F# 计算表达式 : How to use `for` to return a `seq` ?

转载 作者:行者123 更新时间:2023-12-04 22:34:16 25 4
gpt4 key购买 nike

我正在编写一个计算表达式,它本质上是实现 状态单子(monad) 我正在尝试使用 for表达。
我可以使用样板函数 forLoop甚至MBuilder.For() , 他们都返回一个不错的 M<seq<'U>, _>可以进一步处理let!表达。但是当我尝试对 for 做同样的事情时表达式,它无法编译,告诉我 for 中的表达式必须返回 unit .
对于无法缩小的大代码块,我感到很抱歉。

type M<'T, 'E> = 'T * 'E                 // Monadic type is a simple tuple
type MFunc<'T, 'U, 'E> = 'T -> M<'U, 'E> // A function producing monadic value

// typical boilerplate functions
let bind (x: M<'T, 'E>) (f: MFunc<'T, 'U, 'E>) : M<'U, 'E> =
let a, s = x
let b, s1 = f a
b, s1 + s
let combine (e1: M<'T, 'E>) (e2: M<'U, 'E>) : M<'U, 'E> = bind e1 (fun _ -> e2)
let delay f = (fun () -> f())()

// These two are explained below
let combineList (e1: M<'T, 'E>) (e2: M<'T seq, 'E>) : M<'T seq, 'E> =
bind
e1
(fun x1 ->
let e2body, e2state = e2
seq{yield! e2body; yield x1}, e2state
)
let forLoop (xs: seq<'T>) (f: MFunc<'T, 'U, 'E>) : M<seq<'U>, 'E> =
Seq.fold
(fun s x -> combineList (f x) s)
(Seq.empty<'U>, 0)
xs

// Builder class
type MBuilder() =
member this.Bind (x: M<'T, 'E>, f: MFunc<'T, 'U, 'E>) : M<'U, 'E> = bind x f
member this.Return(a) = a, 0
member this.Combine(e1,e2) = combine e1 e2
member this.Delay(f) = delay f
member this.Zero() = (), 0
member this.For (xs: seq<'T>, f: MFunc<'T, 'U, 'E> ) : M<seq<'U>, 'E> = forLoop xs f
let stateful = new MBuilder()

let mTest = stateful {
// below is the typical use, just for example
let! var1 = "q", 3
let! var2 = true, 4
// so far so good, the monad returns ("test", 7)
return "test"
}
现在,我正在尝试使用循环。以下三个调用按预期工作,增加状态的次数与 myList 中的元素一样多。 .他们还返回一个美丽的 string seq ,显然除了最后一次通话:
    let myList = ["one"; "two"; "three"] // define test data

let! var3 = stateful.For(myList, (fun x -> x, 1))
let! var4 = forLoop myList (fun x -> x, 1)

// No return value, as expected
for str in myList do
let! _ = str, 1
return ""
但以下内容无法编译: error FS0001: This expression was expected to have type M<'a,int> but here has type unit
    let! var5 =
for str in myList do
let! _ = str, 1
return ""
所以我的问题是 - 我做错了什么 ?
我也对 For 的两个重载感到困惑。描述 here以及如何利用两者。

最佳答案

您尝试编写的代码在语法上不是有效的计算表达式。该语法不允许表达式 e 中的计算表达式构造。在 let! v = e .

如果要使用嵌套计算表达式,则必须编写:

let mtest = stateful {
let! var5 =
stateful { for str in myList do
let! _ = str, 1
return "" }
return "something here" }

这应该可以回答您的直接问题,但是我发现您的定义有很多令人困惑的地方:
  • 您的 For 的类型令人困惑。它应该是 seq<'T> -> ('T -> M<'R>) -> M<'R> (如果您的 monad 可以组合多个结果)或 seq<'T> -> ('T -> M<unit>) -> M<unit> (如果您的计算只返回一个值)
  • 您有时使用 seq<'T>里面 M<_>在结果中(在 For 中),但有时你的 monad 只返回一个值。您应该在任何地方使用相同的单子(monad)类型。
  • For可以根据 Zero 定义构造。和 Combine .除非您正在做一些特别的事情,否则这是最好的方法。见example in the F# specification .

  • 如果您想要更详细的文档,请查看 at this article ,它描述了各种选项。

    关于F# 计算表达式 : How to use `for` to return a `seq` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11252545/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com