为什么该计算表达式构建器期望“单位"为1?在我的for循环中? [英] Why does this computation expression builder expect "unit" in my for loop?
问题描述
这是对 此版本允许我以前无法做的事情,例如: 但是,我仍然在此方面遇到编译器错误: 在这种情况下,IDE将在 对我来说还不是很清楚,为什么期望循环变量是unit类型.显然,我在某个地方有错误的方法签名,并且我怀疑我没有在应该到达的每个位置传递我的累积状态,但是编译器错误实际上并不能帮助我缩小出错地方.任何建议,将不胜感激. 直接原因是您的 This is a follow-up question to this question. I'm trying to create a computation expression builder that accumulates a value through custom operations, and also supports standard F# language constructs at the same time. For the purposes of having a simple example to talk about, I'm using a computation expression that builds F# lists. Thanks to suggestions from kvb and Daniel I'm further along, but still having trouble with The builder: This version allows for things I could not do before, such as: However, I'm still getting a compiler error on this one: In this case, the IDE is underlining the x in It's not really clear to me why it's expecting the loop variable to be of type unit. Clearly I've got the wrong method signature somewhere, and I suspect I'm not passing through my accumulated state in every place I should be, but the compiler error is really not helping me narrow down where I went wrong. Any suggestions would be appreciated. The immediate cause is that your 这篇关于为什么该计算表达式构建器期望“单位"为1?在我的for循环中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!let stuff =
listBuilder {
let x = 5 * 47
printfn "hey"
add x
addMany [x .. x + 10]
} |> build
let stuff2 =
listBuilder {
for x in 1 .. 50 do
add x
} |> build
for x in
中的x下划线并告诉我:该表达式应该具有unit类型,但此处具有int类型." While
函数限制了body
的类型.但是,通常,您不能在同一计算表达式中同时使用自定义操作和控制流操作符,因此,即使您修复了签名,我也不认为您将能够完全按照自己的意愿进行操作.>for
loops.type Items<'a> = Items of 'a list
type ListBuilder() =
member x.Yield(vars) = Items [], vars
member x.Run(l,_) = l
member x.Zero() = Items [], ()
member x.Delay f = f()
member x.ReturnFrom f = f
member x.Combine((Items curLeft, _), (Items curRight, vars)) =
(Items (curLeft @ curRight), vars)
member x.Bind(m: Items<'a> * 'v, f: 'v -> Items<'a> * 'o) : Items<'a> * 'o =
let (Items current, vals) = m
x.Combine(m, f vals)
member x.While(guard, body) =
if not (guard()) then
x.Zero()
else
x.Bind(body, fun () -> x.While(guard, body))
member x.TryWith(body, handler) =
try
x.ReturnFrom(body())
with e ->
handler e
member x.TryFinally(body, compensation) =
try
x.ReturnFrom(body())
finally
compensation()
member x.Using(disposable:#System.IDisposable, body) =
let body' = fun() -> body disposable
x.TryFinally(body', fun () ->
match disposable with
| null -> ()
| disp -> disp.Dispose())
member x.For(xs:seq<'a>, body) =
x.Using(xs.GetEnumerator(), fun enum ->
x.While(enum.MoveNext, x.Delay(fun () -> body enum.Current)))
[<CustomOperation("add", MaintainsVariableSpace=true)>]
member x.Add((Items current, vars), [<ProjectionParameter>] f) =
Items (current @ [f vars]), vars
[<CustomOperation("addMany", MaintainsVariableSpace=true)>]
member x.AddMany((Items current, vars), [<ProjectionParameter>] f) =
Items (current @ f vars), vars
let listBuilder = ListBuilder()
let build (Items items) = items
let stuff =
listBuilder {
let x = 5 * 47
printfn "hey"
add x
addMany [x .. x + 10]
} |> build
let stuff2 =
listBuilder {
for x in 1 .. 50 do
add x
} |> build
for x in
and telling me, "This expression was expected to have type unit, but here has type int."While
function constrains the type of body
. However, in general you can't use both custom operations and also control flow operators in the same computation expression, so I don't think you'll ever be able to do exactly what you want even if you fix the signature.