I have a following type newtype Arr2 e1 e2 a = Arr2 { getArr2 :: e1 -> e2 -> a }
.
And I got to write Functor instance for it, yet i don't really understand how
I tried
instance Functor (Arr2 e1 e2) where
fmap g (Arr2 a) = Arr2 (g a)
and
instance Functor (Arr2 e1 e2) where
fmap g = g . getArr2
which actually results in type
(a -> b) -> Arr2 e1 e2 a -> b
instead of desired
(a -> b) -> Arr2 e1 e2 a -> Arr2 e1 e2 b
So please, help me
The Functor
class has as definition:
class Functor f where:
fmap :: (a -> b) -> f a -> f b
(<$) :: a -> f b -> f a
The (<$)
has a default implementation: (<$) = fmap . const
which works fine.
So that means that if we enter a function (g :: a -> b
) as first argument, and an Arr2
that produces an a
, we have to generate an Arr2
that calls that g
on the outcome of the arrow if it is applied.
As a result the definition of fmap
for your Arr2
is:
instance Functor (Arr2 e1 e2) where
fmap g (Arr2 a) = Arr2 (\x y -> g (a x y))
Or more elegantly:
instance Functor (Arr2 e1 e2) where
fmap g (Arr2 a) = Arr2 (\x -> g . (a x))
Or a more elegant version - commented by @Alec:
instance Functor (Arr2 e1 e2) where
fmap g (Arr2 a) = Arr2 ((g .) . a)
(you can convert expressions to pointfree ones using this tool)