【问题标题】:When to implement `Zero` member in Computation Expression?何时在计算表达式中实现“零”成员?
【发布时间】:2018-06-22 02:00:43
【问题描述】:

为什么我不能在没有实现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 }

【问题讨论】:

  • 您是否尝试过实现Zero 方法并查看会发生什么?我希望您会感到惊讶 - 问题可能不是您所期望的。

标签: .net f# functional-programming monads computation-expression


【解决方案1】:

此错误似乎是您的示例中一个微妙问题的影响。写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. 你没有为expr2的结果调用return,所以编译器只能猜测这是你想要的,并要求Zero()方法给出maybe { expr2 }的结果值,和
  2. 您在其中的 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 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-12
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 2013-11-04
    相关资源
    最近更新 更多