【问题标题】:F# Computation Expressions and Return statementF# 计算表达式和返回语句
【发布时间】:2014-07-08 11:16:51
【问题描述】:

在 Try F# 网站上,他们给出了一个计算表达式的示例:

type Age =
| PossiblyAlive of int
| NotAlive

type AgeBuilder() =
    member this.Bind(x, f) =
        match x with
        | PossiblyAlive(x) when x >= 0 && x <= 120 -> f(x)
        | _ -> NotAlive
    member this.Delay(f) = f()
    member this.Return(x) = PossiblyAlive x

let age = new AgeBuilder()

let willBeThere (a:int) (y:int) =
  age { 
    let! current = PossiblyAlive a
    let! future = PossiblyAlive (current + y)

    return future
  }

这看起来有点像 Haskell 中的标准 Maybe monad。

但是,在真正的 Haskell 形式中,我想对这两行使用 return:

let! current = PossiblyAlive a
let! future = PossiblyAlive (current + y)

成为:

let! current = return a
let! future = return (current + y)

但是它不起作用。我最接近的是:

let! current = age.Return a
let! future = age.Return (current + y)

但这看起来很脏。有什么方法可以使用return 而不显式使用计算构建器函数?

【问题讨论】:

  • 你的代码对我有用 - 你得到什么错误?
  • 没有错误——关于计算表达式语法和“return”语句。

标签: f# monads computation-expression


【解决方案1】:

您可以创建嵌套表达式:

let! current = age { return a }
let! future = age { return (current + y) }

虽然你可以改用let

let current = a
let future = current + y

请注意,这个构建器违反了 monad 法则,因为

return 150 &gt;&gt;= returnreturn 150不一样

【讨论】:

  • Perfect... 回答了我的问题 - 并证实了我的怀疑,即“返回”定义没有进行边界检查。
【解决方案2】:

我已经更详细地查看了这个问题,并且我认为我已经找到了一个合理的替代方法来使用 Lee 在他的回答中显示的 age { return &lt;expr&gt; } 语法。

我对这种语法的主要不满是我们已经在age monad 中,因此正文中的任何return 语句都应该自动解析为age.Return。然而,解决这个问题对于 F# 团队来说可能是非常低优先级的,因为解决方法非常简单。

我的替代方法是使用一个函数重载Bind 方法,该函数接受一个值,然后将其提升;然后将此提升的值发送到另一个 Bind 函数:

type Age =
| PossiblyAlive of int
| NotAlive

type AgeBuilder() =
    let reasonableAge (x:int) = x >= 0 && x <= 120

    member __.Return x = 
        if reasonableAge x then PossiblyAlive x else NotAlive

    member __.Bind(x:Age, f) =
        match x with
        | PossiblyAlive x when reasonableAge x -> f x
        | _ -> NotAlive

    member this.Bind(x:int, f) =
        this.Bind(this.Return(x), f)

let age = new AgeBuilder()

let willBeThere (a:int) (y:int) =
    age { 
        let! current = a
        let! future = (current + y)
        return future
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-28
    • 2019-09-19
    相关资源
    最近更新 更多