Я проходил некоторое руководство по 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)
Я не вижу разницы.