5
votes

I run into trouble trying to make Vector.Generic.Vector an instance of other typeclasses (in my case - Functor).

I could settle for adding a Functor instance to Vector.Unboxed.Vector, but I couldn't figure out the syntax for that either. My best take was to try something like:

instance (U.Unbox a, U.Unbox b) => Functor U.Vector where
    fmap = U.map

But the compiler (justfully) complained that 'a' and 'b' where nowhere after '=>'. Can I even make this definition for Functor, as it assumes more restrictions on the types fmap is allowed to take?

Most stuff I found in SO was too advanced for me to figure out, so please be gentle :-)

2

2 Answers

8
votes

Think of the type of fmap:

fmap :: Functor f => (a -> b) -> f a -> f b

You are trying to add the constraint that a and b are both instances of Unbox. This is not doable because fmap is completely general while a map of an unboxed Vector is specific to instances Unbox.

It cannot be made a Functor.

4
votes

monadic is correct that this is currently not possible in haskell. However a new language feature currently in the ghc head development branch will make this possible.

The feature is called Constraint Kinds, and (among other features), allows you to add a indexed constraint to a class. Instances of the class can decide what constraint will be needed. A default constraint can be supplied if the instance doesn't declare one.

For example, the Functor class could be rewritten like this:

class Functor m where
  type FunctorCtxt f a :: Constraint
  type FunctorCtxt f a = ()
  fmap :: (FunctorCtx f a, FunctorCtx f b) => f a -> f b

Existing instances such as for lists and Maybe would be unchanged - a default context of nothing is given (any type variable is acceptable). You could though add a new constraint for the Vector instance:

instance Functor U.Vector where
    type FunctorCtxt U.Vector a = U.Unbox a
    fmap = U.map

More details are at in this Constraint Kinds for GHC blog post and KindFact GHC wiki post.

Note that I don't have ghc head installed on my computer, so I wasn't able to test if this would actually work.