【问题标题】:Difference between where bindings, let bindings and the single assignment operator (<-)where 绑定、let 绑定和单个赋值运算符 (<-) 之间的区别
【发布时间】:2012-03-04 11:27:20
【问题描述】:

我不明白这三种语法的区别:

  • where a = f (b)
  • do a &lt;- f (b)
  • do let a = f (b)

尽管a &lt;- f(b) 与其他两个不同,但我确实明白,在大多数情况下,我尝试了所有三个工作。此外,我在网上某处读到,每个块您应该尝试与一个 let 绑定相处,以便“惯用”。但我似乎从来没有管理过。

我如何决定使用什么?

【问题讨论】:

  • 你一定是试错了。我几乎想不出将a &lt;- f b 更改为let a = f b(反之亦然)不会破坏您的代码的情况。那是假设你之后实际使用a
  • @sepp2k 是的,但是您可以轻松地重构代码以使其正常工作。与 let 和 where 相同,需要“次要”重构。正如我所提到的,我知道单个赋值运算符有些不同。我还是想知道有什么区别。
  • 不,你不能。如果f b 具有非单子类型a &lt;- f b 将根本无法编译。您无法进行重构以使其编译(除非您将return 填入其中以进行重构...)。如果f b 确实具有一元类型,则let a = f b 将导致a 具有相同的类型。这几乎肯定会破坏使用a 的代码。
  • @sepp2k 不确定我是否可以在这方面与您“竞争”,但如果我留在同一个 monad 中,这不重要吗?
  • 我不确定你的意思。如果你在一个 do-block 中有多个 &lt;-s,它们各自的右操作数必须在同一个 monad 中。但这与let无关。

标签: haskell syntax binding let do-notation


【解决方案1】:

let foo = bar in ... 只是将foo 定义为与... 上下文中的bar 完全相同;您可以简单地使用文本替换将...foo 的所有用法替换为(bar),并获得完全相同的结果。

where 子句类似于let...in 表达式,但位于函数子句的末尾,而不是表达式。例如,

foo x
    | p1 = ... y ...
    | p2 = ... y ...
  where
    y = ...

如果不将守卫更改为if...then...elses,就无法用let...in 重写它。通常,纯粹出于风格原因,where 子句比 let...in 子句使用。

绑定运算符完全不同。它在do 表示法中用于从一元计算中“提取”一个值。也就是说,如果foo 的类型为m a,那么在x &lt;- foo 之后,x 的类型为a。所有其他“绑定”形式只是定义名称,但 &lt;- 用于将计算结果绑定到 monad 中的名称。 &lt;- 只能在 do 块内使用,因此它专门用于在与您绑定结果的操作相同的 monad 中构建更大的计算。

let foo = bar 中的do 符号只是为了方便;你可以重写:

do let foo = bar
   ...

作为

let foo = bar
in do ...

但是当你有很多这样的绑定时就​​会变得混乱,因为do 块嵌套越来越深。

我不知道你提到的建议在说什么;您可以在 let...in 块中定义多个变量就好了,并且

let foo = ...
    bar ...
in ...

更惯用
let foo = ...
in let bar = ...
   in ...

【讨论】:

    猜你喜欢
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 2014-10-26
    • 2017-01-20
    • 1970-01-01
    • 2013-09-20
    • 2016-09-17
    相关资源
    最近更新 更多