我有一个计算表达式构建器,可以随时建立一个值,并且有许多自定义操作。但是,它不允许标准的 F# 语言结构,而且我在弄清楚如何添加这种支持时遇到了很多麻烦。
举一个独立的例子,这是一个非常简单且毫无意义的计算表达式,用于构建 F# 列表:
type Items<'a> = Items of 'a list
type ListBuilder() =
member x.Yield(()) = Items []
[<CustomOperation("add")>]
member x.Add(Items current, item:'a) =
Items [ yield! current; yield item ]
[<CustomOperation("addMany")>]
member x.AddMany(Items current, items: seq<'a>) =
Items [ yield! current; yield! items ]
let listBuilder = ListBuilder()
let build (Items items) = items
我可以用它来构建列表就好了:
let stuff =
listBuilder {
add 1
add 5
add 7
addMany [ 1..10 ]
add 42
}
|> build
但是,这是一个编译器错误:
listBuilder {
let x = 5 * 39
add x
}
// This expression was expected to have type unit, but
// here has type int.
这是这样的:
listBuilder {
for x = 1 to 50 do
add x
}
// This control construct may only be used if the computation expression builder
// defines a For method.
我已经阅读了我能找到的所有文档和示例,但有些东西我没有得到。我尝试的每一个.Bind()
或.For()
方法签名只会导致越来越多的令人困惑的编译器错误。我可以找到的大多数示例要么在您进行过程中建立一个值,要么允许使用常规的 F# 语言结构,但我无法找到一个同时具备这两种功能的示例。
如果有人可以通过向我展示如何采用此示例并在构建器中添加对let
绑定和for
循环的支持来为我指明正确的方向(至少 - using
,while
并且try/catch
会很棒,但如果有人让我开始,我可能会弄清楚这些)然后我将能够感激地把这个教训应用到我的实际问题上。