I was going through some Arrow tutorial, toying with functions returning a new version of themselves in an attempt to maintain some state.
The new type is defined like that:
newtype Circuit a b = Circuit {runCircuit :: a -> (b, Circuit a b)}
Because I want to be able to compose circuits I make it an instance of Category. When composing two circuits, the result must also be a circuit. (Circuit b c) . (Circuit a b)
gives a Circuit a c
.
I wrote this :
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)
but it fails:
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
I looked up the answer in the tutorial and this answer was introducing an intermediate function like this, which compiles nicely:
(.) = 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)
I fail to see the difference.
The .
in new_g . new_f
is from the prelude, not from Control.Category
. So you need to use Cat..
.
But the usual way to use Control.Category
is:
import Prelude hiding (id, (.))
import Control.Category
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With