2014-12-21 80 views
1

我需要編寫以下功能:哈斯克爾麻煩寫綁定功能單子例如

bind :: ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action) 

行動是我定義的類型構造。麻煩的是,當我嘗試實現它以下列方式:

bind f g = 

我不知道怎麼打發類型的值「a」的函數g。我無能爲力地獲得價值。

事實上,這看起來像某種將一種功能轉換爲另一種功能,但我也不知道如何實現這一功能。

我該怎麼做才能使這種轉變成爲可能?

+0

看那'chainCPS'功能[這裏](http://en.wikibooks.org/wiki/Haskell/Continuation_passing_style)。 – user3237465

+2

使用Djinn。它爲你實現。 – augustss

+1

這是Erik Meijer的fp101x練習。如果您將作業外包,您將無法學習。課程材料中有相當多的指導:「現在你可以讓這些類型引導你唯一合理的實現。」 - 甚至Djinn實際上也會爲你找到合適的例子,你可以自己做這個練習,甚至可以用紙筆做。解決方案很短。不要破壞「尤里卡」時刻。 – phadej

回答

5

這是Cont monad bind。如果沒有NEWTYPE包裝它看起來像這樣:

bind :: ((a -> r) -> r) -> (a -> ((b -> r) -> r)) -> ((b -> r) -> r) 

首先,刪除多餘的括號:

bind :: ((a -> r) -> r) -> (a -> (b -> r) -> r) -> (b -> r) -> r 

其次,讓b -> r = br

bind :: ((a -> r) -> r) -> (a -> br -> r) -> br -> r 

現在你有

bind s f k = ? 

其中s :: (a -> r) -> r,f :: a -> br -> rk :: br

而且

flip f k  :: a -> r 
s (flip f k) :: r 

所以

bind :: ((a -> r) -> r) -> (a -> ((b -> r) -> r)) -> ((b -> r) -> r) 
bind s f k = s (flip f k) 

或者乾脆

bind s f = s . flip f 

或者在pointfree

bind = (. flip) . (.) 
3

你的monad被稱爲continuation monad Cont r a = ((a->r)->r)(減去一個新類型包裝),其中r = Action在你的情況。但是,讓我們冒險一點沒有看單子即是如何定義的?

讓我們大膽地開始:

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action) 
bind f g = (??? :: (b -> Action) -> Action) 

所以,讓我們開始填充???。我們需要製作一個功能,讓我們利用該拉姆達:

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action) 
bind f g = \k :: (b -> Action) -> (??? :: Action) 

一旦已經克服了,現在我們需要一個手藝Action。我們有幾個函數返回:f,g,k,每個函數都需要不同的參數。這是一個反覆試驗的問題。我們猜... f

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action) 
bind f g = \k :: (b -> Action) -> f (??? :: a -> Action) 

我們再次需要一個功能:灑更多的lambda,更多的lambda!

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action) 
bind f g = \k :: (b -> Action) -> f (\x :: a -> (??? :: Action)) 

Groan ...,我們需要再次生成Action。我們做了什麼毫無意義的事情?我們循環圈? 沒有,我們現在有x :: a的範圍,所以我們現在的權力在增長。讓我們用g現在:

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action) 
bind f g = \k :: (b -> Action) -> f (\x :: a -> g (???1 : a) (???2 :: b -> Action)) 

嗯,g第一個參數是現在瑣碎找到。

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action) 
bind f g = \k :: (b -> Action) -> f (\x :: a -> g x (???2 :: b -> Action)) 

更多lambdas,更多lambdas!

bind :: forall a b. ((a -> Action) -> Action) -> (a -> ((b -> Action) -> Action)) -> ((b -> Action) -> Action) 
bind f g = \k :: (b -> Action) -> f (\x :: a -> g x (\y :: b -> (??? :: Action))) 

唉!不是另一種Action來生產!但一切都沒有失去,我們的力量不斷增強:我們現在有x::ay::b在我們的電話!我們也從來沒有使用過k ...嗯....

要做到:

  1. 擊敗最後???
  2. 爲monad提供return/unit函數。
  3. 證明單子法。
  4. 利潤!