2011-07-06 51 views
2

一個簡單的問題: 給出的定義,(從哈斯克爾SOE)哈斯克爾單子形成

do x — el; el\ ...; en 
    => el »= \x — do e2\ ...; en 

和:

do let decllist; el\...; en 
=> let decllist in do e2\ ...; en 

看來,這兩個結構是相同的:

do let x = e1 
    e2 

and

do x <- e1 
    e2 

都評估e1,將其綁定到e2,然後評估e2。

是嗎?

回答

4

讓我們做的Maybe單子一個簡單的例子:

foo = do 
     let x = Just 1 
     return x 

bar = do 
     x <- Just 1 
     return x 

脫糖都,我們得到

foo = let x = Just 1 in return x -- do notation desugaring 
    = return (Just 1)    -- let 
    = Just (Just 1)     -- definition of return for the Maybe monad 

bar = let ok x = return x in Just 1 >>= ok -- do notation desugaring 
    = let ok x = return x in ok 1 -- definition of >>= for the Maybe monad 
    = return 1      -- definiton of ok 
    = Just 1      -- definition of return for the Maybe monad 

僅供參考,我使用的是translation from section 3.14 of the Haskell 2010 Report

0

x <- e1轉換爲e1 >>= \x ->,一個不完整的表達;表達式let只是一個正常的let。或者你問,如果let(>>=)是相同的東西?它們並不是:(>>=)將monad包裝的東西暴露給函數,它必須產生包裹在monad中的東西。換句話說,與x <- e1e1的類型必須是IO a對於一些a,但與let x = e1e1的類型只是a;在這兩種情況下,x的類型將是a

+0

'do'-表達式中的'let'不僅僅是一個正常的'let'表達式。這是一個'let'語句(Haskell 2010 Report,3.14節)。 'let'語句解析爲'let'表達式,但它本身不是'let'表達式。同樣,'e1 >> = \ x - >'也沒有意義。最好只看報告中的翻譯規則。 – Lambdageek

1

假設e1Monad m => m a類型的計算,那麼let x = e1x <- e1意味着有些不同的東西。

let -version中,當您在do-expression中使用x時,您正在處理的值爲Monad m => m a

在另一個版本中,當您在do表達式中使用x時,您正在處理類型爲a的值(因爲do-notation隱式地處理monad上的映射)。

例如:

e :: IO Int 
f :: Int -> Int 

-- the following will result in a type error, since f operates on `Int`, not `IO Int`: 
g = do let x = e 
     return $ f x 

-- the following will work: 
g' = do x <- e 
     return $ f x 
+0

謝謝。 Monads讓我想起量子力學 - 「如果你認爲你理解他們,你就不會」! :-) – guthrie

+0

在我的例子中; e :: Int,所以「let」會起作用,而不是箭頭 - 是的? – guthrie

+0

@Guthrie哦,如果'e :: Int',那麼你確實需要使用'let'。 –

3

不,他們是不一樣的。例如,

do let x = getLine 
    print x 

轉化爲

let x = getLine in print x 

這是一種類型的錯誤,如x將具有類型IO String。我們要求打印計算本身,而不是結果。


do x <- getLine 
    print x 

轉化爲

getLine >>= \x -> print x 

這裏x勢必作爲計算的結果,並且其類型是String,所以這種類型的檢查。


do -notation,let只是結合值的名字,如它總是這樣,當<-用於執行一元綁定,這是一個名稱綁定到結果的計算

+0

謝謝,非常清楚 - 綁定到不同的東西。 – guthrie