Я просматривал учебник по стрелкам , играя с функциями, возвращающими новую версию себя в попытке сохранить какое-то состояние.
Новый тип определяется следующим образом:
newtype Circuit a b = Circuit {runCircuit :: a -> (b, Circuit a b)}
Поскольку я хочу иметь возможность составлять схемы, я делаю его экземпляром Category. При составлении двух цепей результатом также должна быть цепь. (Контур b c). (Схема a b)
дает схему 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)
Я не вижу разницы.