2012-01-09 47 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

相关问题