2011-09-10 61 views
8

關於Haskell的奇妙之處。函數的類型幾乎決定了它的實現。這是這一個情況,但是......我的大腦僅僅是繞不嵌套函數的東西在這裏包裝:如何在Haskell中實現這個功能

mkDyn :: (Typeable a) => ((a -> IO()) -> IO()) -> ((Dynamic -> IO()) -> IO()) 

唯一的問題是如何處理錯誤,將被要求fromDynamic呼叫處理,但是......一旦我有了其餘的想法,我可以解決這個問題。我猜將會需要像下面的某個地方。但我似乎無法弄清楚包裝lambda的東西。

case fromDynamic x of 
    Just x -> f x 
    Nothing -> undefined -- TODO 
+1

哇,我什至不知道Haskell有動態類型的支持,更不用說它是[可在基地](http://hackage.haskell.org/packages/archive/base/latest/doc/html/數據Dynamic.html)。每天學些新東西。 –

+0

@Joey IIRC甚至有一個庫可以用簡單的賦值操作符來編寫命令式代碼,但是我忘記了在哪裏。我認爲它在Planet Haskell上曾經提到過。 – fuz

回答

10

我想你想toDyn,不fromDynamic。因此,讓我們做到這一點緩緩道:

mkDyn :: Typeable a => 
     ((a -> IO()) -> IO()) 
     -> (Dynamic -> IO()) 
     -> IO() 
mkDyn k f = ... 

退貨類型應該是IO(),我們可以通過調用kf獲得。調用f對我們沒有多大幫助,因爲我們會以某種方式實現Dynamic,但我們不能從k那樣做(明智地)。所以我們打電話給kk需要另一個函數作爲它的參數,所以讓我們開始像這樣:

mkDyn k f = k (\a -> ...) 

所以函數的參數爲​​Typeable a => a -> IO()。我們沒有這種類型的功能,但我們有一個類型爲Dynamic -> IO()的功能。由於Typeable約束,我們可以使用toDyn把我們aDynamic並獲得:

mkDyn k f = k (\a -> f (toDyn a)) 

有更簡單的實現(例如,return()k (\a -> return()),但是這一次似乎是有意義

+0

mkDyn k f = k $ f。 toDyn – rampion

+3

@rampion兩個可以玩那個遊戲! 'mkDyn =(。(。toDyn))'。 –

+2

我傾向於喜歡指出的版本。如果事情真的只是一個簡單的流水線,我只使用無點式。任何(甚至稍微)更復雜,我會在下次閱讀代碼時感到後悔。 – nominolo

4

我被騙和所使用的Djinn program

我第一廣義給出的類型:

f :: (a -> c) 
    -> ((a -> b) -> b) 
    -> ((c -> b) -> b) 

(a -> c)代表toDyn function函數,而c代表Dynamicb代表IO()

巨靈的結果是出奇的簡單:

@djinn (a -> c) -> ((a -> b) -> b) -> ((c -> b) -> b) 
f a b c = b (\ d -> c (a d)) 

使其更加具體的(通過與toDyn功能替換(a -> c)),我們得到:

mkDyn :: (Typeable a) => ((a -> IO()) -> IO()) -> ((Dynamic -> IO()) -> IO()) 
mkDyn b c = b (\ d -> c (toDyn d)) 

它匹配nominolo's answer

+1

這是否證明nominolo是djinn? – Landei