什么时候在计算表达式中实现“零”成员?
When to implement `Zero` member in Computation Expression?
为什么在没有实现 Zero
成员的计算表达式中不能使用 pattern matching function
?
例如,有人可以解释为什么允许 pattern matching expression
但不允许 pattern matching function
吗?
type MaybeBuilder() =
member __.Bind (x, f) = match x with Some a -> f a | None -> None
member __.Return x = Some x
let maybe = MaybeBuilder()
// Errors: FS0708 This control construct may only be used
// if the computation expression builder defines a 'Zero' method
maybe { Some 1 |> function Some x -> return x | None -> return 0 }
maybe { Some 1 |> fun x -> match x with Some x' -> return x' | None -> return 0 }
// Ok
maybe { match Some 1 with Some x -> return x | None -> return 0 }
这个错误似乎是您的示例中的一个细微问题造成的。当你写成maybe { Some 1 |> function Some x -> return x | None -> return 0 }
,就相当于下面的代码
let expr1 = function Some x -> return x | None -> return 0
let expr2 = Some 1 |> expr1
maybe { expr2 }
这表明
- 你没有为
expr2
的结果调用 return
,所以编译器只能猜测那是你想要的,并要求 Zero()
方法给出值maybe { expr2 }
和 的结果
- 你的
return
调用在错误的范围内使用(如果你这样拆分你的代码,编译器会抱怨)所以即使你实现 Zero()
,它也不会'编译。
要解决这个问题,您可以将函数重写为
maybe { return Some 1 |> function Some x -> x | None -> 0 }
或者您可以在 expr1
函数的分支中添加 maybe
计算表达式。在这个例子中它看起来很糟糕,但对于更复杂的逻辑可能是可行的,这些逻辑可能并不都在 maybe { }
builder
的上下文中
Some 1 |> function Some x -> maybe { return x } | None -> maybe { return 0 }
为什么在没有实现 Zero
成员的计算表达式中不能使用 pattern matching function
?
例如,有人可以解释为什么允许 pattern matching expression
但不允许 pattern matching function
吗?
type MaybeBuilder() =
member __.Bind (x, f) = match x with Some a -> f a | None -> None
member __.Return x = Some x
let maybe = MaybeBuilder()
// Errors: FS0708 This control construct may only be used
// if the computation expression builder defines a 'Zero' method
maybe { Some 1 |> function Some x -> return x | None -> return 0 }
maybe { Some 1 |> fun x -> match x with Some x' -> return x' | None -> return 0 }
// Ok
maybe { match Some 1 with Some x -> return x | None -> return 0 }
这个错误似乎是您的示例中的一个细微问题造成的。当你写成maybe { Some 1 |> function Some x -> return x | None -> return 0 }
,就相当于下面的代码
let expr1 = function Some x -> return x | None -> return 0
let expr2 = Some 1 |> expr1
maybe { expr2 }
这表明
- 你没有为
expr2
的结果调用return
,所以编译器只能猜测那是你想要的,并要求Zero()
方法给出值maybe { expr2 }
和 的结果
- 你的
return
调用在错误的范围内使用(如果你这样拆分你的代码,编译器会抱怨)所以即使你实现Zero()
,它也不会'编译。
要解决这个问题,您可以将函数重写为
maybe { return Some 1 |> function Some x -> x | None -> 0 }
或者您可以在 expr1
函数的分支中添加 maybe
计算表达式。在这个例子中它看起来很糟糕,但对于更复杂的逻辑可能是可行的,这些逻辑可能并不都在 maybe { }
builder
Some 1 |> function Some x -> maybe { return x } | None -> maybe { return 0 }