2014-06-10 65 views
7

我玩弄CPS和Control.Monad.Cont,並想知道我們通過注意monadic結構獲得什麼。對於這樣的代碼:Cont的monad實例有什麼好處?

sumOfSquares'cps :: Cont r Int -> Cont r Int -> Cont r Int 
sumOfSquares'cps x y = x >>= \x' -> 
         y >>= \y' -> 
         return (x'*x' + y'*y') 

可以很容易地改寫爲

type Cont' r a = (a -> r) -> r 

sos'cps :: Cont' r Int -> Cont' r Int -> Cont' r Int 
sos'cps x y = \k -> x $ \x' -> 
        y $ \y' -> 
        k (x'*x' + y'*y') 

不要誤會我的意思,但我不能從能夠使用do符號看到這裏的感覺除了和newtype。我不認爲callCC也依賴monad實例。

我想象不出一個例子。我們實際上得到了什麼來聲明Cont r monad?

+3

「我不認爲'callCC'依賴monad實例」。嚴格地說,從來沒有。例如,在Maybe'monad'return = Just'和'(= <<)=也許Nothing'中。 Monad類抽象出先前存在的功能,以使Michael Snoyman在他的回答中提到的可能性。 – duplode

+0

有意思,思考一下。雖然通常當我看到使用綁定的重構函數時,我在我的胃裏感受到一種溫暖的溫暖感覺,這告訴我我做了正確的事情。我不明白'Cont',因爲在語法上我沒有真正的區別。 –

+1

要理解爲什麼句法糖對於'Cont'看起來特別薄,你可能想查看[The Monads of Monads]​​(http://blog.sigfpe.com/2008/12/mother-of-all- monads.html)。 –

回答

9

你可能會問同樣的問題任何Monad。關閉我的頭頂,我能想到的三個優點:

  1. 您可以訪問的,旨在與Monad s到工作職能的巨大集合。
  2. 您可以使用do -notation。
  3. 你可以疊加monad變壓器來創建更強大的功能。

這也可以讓你更好地理解你的代碼,因爲你可以依靠身份和關聯屬性等。

+1

這些都是發佈問題後彈出到我腦海中的東西:)。我想我對另一個monad中綁定操作符使代碼類型整齊的幾乎相同的語法感到失望。這太天真了,因爲monads服務的目的不同於增強語法。 –

6

一個明顯的優點是,您可以使用爲Monads(和Functors)定義的組合器。例如,你的函數可以使用liftM2寫成:

sumOfSquares'cps :: Cont r Int -> Cont r Int -> Cont r Int 
sumOfSquares'cps = liftM2 sumSquares 
    where sumSquares x y = x * x + y * y 

此功能不依賴於單子是Cont並可以用更通用的類型例如寫

sumOfSquaresM :: Monad m => m Int -> m Int -> m Int