2

为什么我不能pattern matching function在没有实现Zero成员的计算表达式中使用?

例如,有人可以解释为什么它允许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 }
4

1 回答 1

3

此错误似乎是您的示例中一个微妙问题的影响。写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 }

这表明

  1. 您没有要求return的结果expr2,因此编译器只能猜测这是您想要的,并要求Zero()方法给出结果的值maybe { expr2 },并且
  2. 您在那里的return调用在错误的范围内使用(如果您像这样拆分代码,编译器会抱怨)所以即使您实现Zero(),它也不会编译。

要解决此问题,您可以将函数重写为

maybe { return Some 1 |> function Some x -> x | None -> 0 }

或者您可以在函数maybe的分支中添加计算表达式。expr1在这个例子中它看起来很糟糕,但对于更复杂的逻辑可能是可行的,这些逻辑可能并不都在maybe { }builder的上下文中

Some 1 |> function Some x -> maybe { return x } | None -> maybe { return 0 }
于 2018-01-12T15:50:12.813 回答