Estaba pasando por some Arrow tutorial, jugando con funciones que devuelven una nueva versión de sí mismos en un intento de mantener algún estado.¿Qué hay de malo en definir la composición de esta manera?
El nuevo tipo se define así:
newtype Circuit a b = Circuit {runCircuit :: a -> (b, Circuit a b)}
Porque quiero ser capaz de componer circuitos que hacen que sea una instancia de Categoría. Al componer dos circuitos, el resultado también debe ser un circuito. (Circuit b c) . (Circuit a b)
da un Circuit a c
.
me escribió esto:
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)
pero falla:
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
busqué la respuesta en el tutorial y esta respuesta fue la introducción de una función intermedia de este tipo, que recoge muy bien:
(.) = 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)
No veo la diferencia.
perfecto, añadiendo 'Cat.' simplemente funciona. Gracias por el consejo, ahora veo por qué querríamos ocultar la identificación y (.). – Niriel