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

Reply via email to