haskell - 为什么在 do block 中需要 let 关键字?

标签 haskell let

let的原因是什么在 do堵塞。

-- codeblock A
main = do
  let a = 0
  let f a = a + 1
  let b = f 0
  print (a,b)

-- codeblock B
main = do
  a = 0
  f a = a + 1
  b = f 0
  print (a,b)

假设所有 let没有 in必须跟= (这是真的?)

编译器应该能够暗示let来自 =和预处理/脱糖codeblock Bcodeblock A
使用 let在这种情况下似乎是不必要的,就像你可以写 codeblock C但选择写codeblock D
-- codeblock C
main = do
  print (a,b)

a = 0
f a = a + 1
b = f 0

-- codeblock D
main = do
  print (a,b)

function  a = 0
function  f a = a + 1
function  b = f 0

为了澄清我的假设不包括 let紧随其后的是 in应该保持不变。
-- codeblock E
main = do
  a = 0
  f a = a + 1
  b = f 0
  c = let d = 1 
          e = 1
      in d + e
  print (a,b,c)

最佳答案

我不知道为什么这样做,但这是我可以想象的一个原因:它允许您指定应按顺序建立哪些绑定(bind),以及同时建立哪些绑定(bind),这在阴影的情况下可能很重要。

例如,假设您的建议得到实现,然后考虑:

foo :: [Int]
foo = do
  x <- return [1]
  y = 0:x
  x = [1..5]
  y

有两种合理的方法可以脱糖:
foo1 :: [Int]
foo1 = do
  x <- return [1]
  let y = 0:x
  let x = [1..5]
  y

foo2 :: [Int]
foo2 = do
  x <- return [1]
  let y = 0:x
      x = [1..5]
  y
foo1计算结果为 [0,1] , 和 foo2[0,1,2,3,4,5] .当然,这是一种奇怪的代码编写方式,但事实上 let必须明确表示您的意图没有歧义。

正如 chi 的评论中所述,阴影不是您可能需要明确说明您的 let 的唯一原因。绑定(bind)是分组的:一个函数定义可能需要多个方程,以匹配多个参数模式。

关于haskell - 为什么在 do block 中需要 let 关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40647332/

相关文章:

python - 从 Python 生成和运行 Haskell 代码

haskell - 与 Haskell 交互使用串行端口

haskell - 我该怎么做才能消除此 Reflex.Dom 代码中的 unsafePerformIO?

LET block 内的嵌套 FLET block (反之亦然)

racket - Define 相对于 Let 的优点

haskell - 使用 reader monad 比直接传递值有什么优势?

haskell - 由于路径长度限制,我如何解决 Windows 上的 cabal 沙箱构建错误?

javascript - 为什么 let 在 for 循环之后比在 for 循环之前慢得多?

performance - `let` 在 Clojure 中是如何实现的,它的开销是多少?

ruby - RSPEC Let 与创建昂贵对象的实例