2016-01-07 36 views
3

所以我想明白Haskell do表示法的工作原理。 我知道它与单子一起使用,它基本上扩展(因为它实际上是语法糖)到与绑定(>>=)或(>>)连接的匿名函数中,如https://en.wikibooks.org/wiki/Haskell/Syntactic_sugar#Do_notation所示。Haskell:'do [1,2,3]; [“你好”]'行为澄清

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

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

回报

"hellohellohello" 

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

+6

此外,正确的术语是“列表”,因为“数组”通常被理解为在内存中连续排列。 –

+4

'do x < - [“baby,”,“darling”,“ragtime gal”]; “你好我的”++ x' –

回答

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

desugars到

[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" 
+0

哇,谢谢!现在我知道我在找什么了,似乎这(或多或少)是如何为数组定义绑定“>> =”运算符(请参阅https://en.wikipedia.org/wiki/Monad_%28functional_programming%29 #Syntactic_sugar:_do-notation) 重要部分是'm >> = f = concat(map fm)' – Andreas

+2

我认为这里的关键是'list >> = f'被定义为'concatMap f list'。直觉是列表表示一个非确定性计算,所以'[1,2,3]'是一个具有三个可能输出的计算。当你用函数绑定它时,结果是该函数应用于所有可能的输出。 –

3

为了补充约阿希姆·布莱特纳的答案,下面就来看看在这从另一个角度:

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 

当然,对于东西(不管这东西,说的订购数量,字符数等)列表(不是“阵列”)列表内涵desugar到使用同一代码concatMap ‐;但它有时更容易在心理上处理它们,或者是作为一些嵌套的回路的规范

事实上,看起来do -notation首先可能很容易就是for -notation。