2016-01-07 87 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。