5

考虑以下有效的 Haskell 代码

module Main where

main :: IO ()
main = do
  let x = f
  print x

f :: Maybe (Int, Int)
f =
  Just 3 >>= (\a ->
    Just 5 >>= (\b ->
      return (a, b)))

函数f可以用这样的 do-notation 等效地重写

f :: Maybe (Int, Int)
f = do
  a <- Just 3
  b <- Just 5
  return (a, b)

让我烦恼的是,当我将内联的内容放入时,do 表示法不起作用f。以下代码甚至不解析:

main :: IO ()
main = do
  let x = do
    a <- Just 3
    b <- Just 5
    return (a, b)
  print x

我是否正确,let我被迫诉诸于内心(>>=)

当我这样做时,以下代码也不会解析:

module Main where

main :: IO ()
main = do
  let x =
    Just 3 >>= (\a ->
      Just 5 >>= (\b ->
        return (a, b)))
  print x

除了let. 有没有优雅的使用方式bindinside let

4

1 回答 1

8

我是否正确,let我被迫诉诸于内心(>>=)

不:

main :: IO ()
main = do
  let x = do
      a <- Just 3
      b <- Just 5
      return (a, b)
  print x

Haskell 的布局规则规定 mus 中绑定的主体e至少p = e与开头p(或第一个绑定,如果您同时使用多个)一样多。由于let遵循do(几乎)与 相同的规则let … in,您可以使用以下函数验证这一点:

f :: Int
f = 
  let x =
    3 + 5
  in x

这不起作用,因为3 + 5没有与x. 然而,

f :: Int
f =
  let x =
       3 + 5
  in x

作品。此外,虽然main上述方法有效,但它并没有真正传达这一点a并且bx'do块中的东西,所以稍微缩进它们会更好一点:

main :: IO ()
main = do
  let x = do
        a <- Just 3
        b <- Just 5
        return (a, b)
  print x
于 2015-11-27T18:42:07.680 回答