6

我正在阅读一些箭头教程,玩弄返回自己新版本的函数以试图保持某种状态。

新类型的定义如下:

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

因为我希望能够组成电路,所以我将其设为 Category 的一个实例。组成两个电路时,结果也必须是一个电路。 (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)

我看不出有什么区别。

4

1 回答 1

10

.in来自前奏曲,而new_g . new_f不是来自Control.Category. 所以你需要使用Cat...

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

import Prelude hiding (id, (.))
import Control.Category
于 2012-01-09T11:04:49.203 回答