2012-01-09 55 views
6

我正在通過some Arrow tutorial,嘗試返回自己的新版本以試圖維持某種狀態。以這種方式定義構圖有什麼問題?

新類型定義那樣:

newtype Circuit a b = Circuit {runCircuit :: a -> (b, Circuit a b)} 

因爲我希望能夠組成電路我做IT類的一個實例。當組成兩個電路時,結果也必須是一個電路。 (Circuit b c) . (Circuit a b)給出Circuit a c

我寫了這個:

import qualified Control.Category as Cat 
instance Cat.Category Circuit where 
    (Circuit g) . (Circuit f) = Circuit $ \a -> let 
                (b, new_f) = f a 
                (c, new_g) = g b 
                new_circ = new_g . new_f 
               in (c, new_circ) 

但它失敗:

Main.hs:70:64: 
    Couldn't match expected type `b0 -> c0' 
       with actual type `Circuit b c' 
    In the first argument of `(.)', namely `new_g' 
    In the expression: new_g . new_f 
    In an equation for `new_circ': new_circ = new_g . new_f 

我的教程擡頭的答案,這個答案是引入這樣一箇中間功能,編譯很好:

(.) = dot where 
    (Circuit g) `dot` (Circuit f) = Circuit $ \a -> let 
                 (b, new_f) = f a 
                 (c, new_g) = g b 
                 new_circ = new_g `dot` new_f 
                in (c, new_circ) 

我看不出差別。

回答

10

. in new_g . new_f是從前奏而不是從Control.Category。所以你需要使用Cat..

但使用Control.Category通常的方式是:

import Prelude hiding (id, (.)) 
import Control.Category 
+0

完善,加上'Cat.'只是工作。感謝您的建議,我現在看到爲什麼我們想隱藏id和(。)。 – Niriel 2012-01-09 11:20:36