For strange reasons I won't get into here, I would like to implement an
instance of the Functor class for various function types with 1 or more
arguments. I want fmap to transform the result of the function, as
opposed to transforming the first argument.
Once I figured out the syntax, the instance for (a->b) was easy:
instance Functor ((->) a) where
fmap g f x = g (f x)
-- or, to be cute, fmap = (.)
Bear in mind that the "kind" of the Functor class is *->*, so instances
of that class need to have the same kind. For functions with 2 or more
arguments, I'm stuck. I'd like to do this:
instance Functor (a->b->) where
fmap g f x y = g (f x y)
...but of course it has invalid syntax. I can't think of a way to write
(a->b->) in the ((->) a) form. (a->b->c) would be ((->) a ((->) b c)).
I tried a type synonym:
type Func2 a b c = (a->b->c)
instance Functor (Func2 a b) where
fmap g f x y = g (f x y)
That doesn't work either: Haskell98 doesn't allow type synonyms to be
used to define instances. GHC supposedly lifts this restriction, but it
complains: (I'm using version 4.02)
> type synonym `Func2' should have 3 arguments, but has been given 2
> When checking kinds in `Func2 a b'
> When checking kinds in `Functor (Func2 a b)'
So I guess GHC only accepts type synonyms as instances when the kind of
the class is *. I could use a datatype renaming (newtype) to accomplish
this:
newtype Func2 a b c = Func2 (a->b->c)
instance Functor (Func2 a b) where
fmap g (Func2 f) = Func2 (\x y -> g (f x y))
...but I think this is ugly and it really doesn't accomplish what I
want.
Any ideas?
Thanks,
Matt Harden