Haskell: 'do [1,2,3]; ["hello"]' 行为说明

Haskell: 'do [1,2,3]; ["hello"]' behavior clarification

所以我试图准确理解 Haskell do 符号的工作原理。 我知道它与 monads 一起使用,并且它基本上扩展(因为它实际上是语法糖)为与 bind (>>=) 或 then (>>) 连接的匿名函数,如此处所示 https://en.wikibooks.org/wiki/Haskell/Syntactic_sugar#Do_notation.

但是我的问题是为什么下面的命令

Prelude> do [1, 2, 3]; "hello"

returns

"hellohellohello"

我知道数组实际上是 monad(字符串是字符数组),但我看不出这是如何导致上述行为的。

do [1, 2, 3]; "hello"

脱糖为

[1, 2, 3] >> "hello"

相同
[1, 2, 3] >>= (\_ -> "hello")

相同
concatMap (\_ -> "hello") [1, 2, 3]

相同
concat (map (\_ -> "hello") [1, 2, 3])

相同
concat [(\_ -> "hello") 1, (\_ -> "hello") 2, (\_ -> "hello") 3])

相同
concat ["hello","hello","hello"]

相同
"hellohellohello"

为了补充 Joachim Breitner 的回答,请从另一个角度看一下:

do [1, 2, 3]
   "hello"

do a <- [1, 2, 3]
   b <- "hello"
   return b

do a <- [1, 2, 3]
   do b <- "hello"
      do return b

[b | a <- [1,2,3], b <- "hello"]

与伪代码相同

for a in (a list of Nums) [1, 2, 3]:
   -- here we have `a` (a Num)
   for b in (a list of Chars) "hello":
      -- here we have that same `a` (a Num), 
      -- and `b` (which is a Char)
      emit b       -- whatever "emit" means

当然,列表理解 lists(不是 "arrays")的 stuff(不管那东西是什么,说 Nums , 字符等) 脱糖成相同的 concatMap‐ 使用代码;但有时更容易在头脑中处理它们,无论是按原样,还是作为某些嵌套 循环 的规范。

事实上,do-notation 似乎很容易成为 for-notation。