Search code examples
typeclassfunctorpurescript

Type kind error when creating instance of Functor typeclass


I'm trying to implement Functor typeclass instance for a very trivial type Foo:

data Foo a = Foo a

instance functorFoo :: Functor (Foo a) where
  map fn (Foo a) = Foo (fn a)

Purescript gives me not-so-helpful error message:

Could not match kind

    Type -> Type

with kind

    Type

What does it mean? I'm not yet really familiar with the Kind-system.


Solution

  • But I'd still like to find out why does the first version not work. Like how does the Functor typeclass differ from e.g. Semigroup where the first version worked just fine.

    Let's look at the definition of the Functor type class:

    class Functor f where
      map :: forall a b. (a -> b) -> f a -> f b
    

    It contains f a and f b types in the type signature of map which clearly indicates that f is of kind Type -> Type (it "carries" another type). On the other hand Semigroup clearly relates to plain types of kind Type:

    class Semigroup a where
      append :: a -> a -> a
    

    So Semigroup is a class which can be defined for plain types like String, Int, List a, Map k v or even a function a -> b (which can also be written as (->) a b) but not type constructors which require another type like List Map k (->) a (I have to use this notation here).

    On the other hand Functor class requires type constructors so you can have instances like Functor List, Functor (Map k) or Functor ((->) a).