[Haskell-cafe] Type parameters in type families

Ryan Ingram ryani.spam at gmail.com
Mon Mar 17 21:12:35 EDT 2008


On 3/17/08, Hugo Pacheco <hpacheco at gmail.com> wrote:
> type family G a :: * -> *
> type instance G Int = Either () -- you forgot this line
>
> instance Functor (G Int) where
>    fmap f (Left ()) = Left ()
>    fmap f (Right x) = Right (f x)

One thing that you don't seem to be clear about is that there is
something slightly magic going on in this Functor definition; you are
not declaring Functor (G Int) but rather Functor (whatever (G Int)
turns into).  This is using a GHC extension "TypeSynonymInstances".
The extension allows you to use type synonyms when declaring
instances, but only if they are fully applied, and the compiler is
simply applying the substitution for you.

That is to say, this code is no different than the following:

type family G a :: * -> *
type instance G Int = Either ()
instance Functor (Either ()) where
    fmap f (Left ()) = Left ()
    fmap f (Right x) = Right (f x)

Once you declare a more complicated type function, such as
   type family F a x :: *
this extension can no longer come into play.

You can get around this restriction with a newtype:

type family F a x :: *
type instance F Int x = Either () x

newtype F' a b = F' (F a b)

instance Functor (F' Int) where
   fmap f (F' (Left ())) = F' (Left ())
   fmap f (F' (Right x)) = F' (Right $ f x)


More information about the Haskell-Cafe mailing list