Что не так с определением композиции таким образом? - PullRequest
6 голосов
/ 09 января 2012

Я проходил некоторое руководство по Arrow , играя с функциями, возвращающими новую версию себя в попытке сохранить какое-то состояние.

Новый тип определен так:

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)

Я не вижу разницы.

1 Ответ

10 голосов
/ 09 января 2012

. в new_g . new_f от прелюдии, а не от Control.Category. Так что вам нужно использовать Cat...

Но обычный способ использования Control.Category:

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