haskell constraint families

haskell, types

Solution

There's a few odd things going on in your definition. First of all, the class variable `f` is never mentioned in the type of the (only) class method `next`. How is the compiler supposed to choose which instance of the type class to use? I'm going to assume you meant this:

{-# LANGUAGE ConstraintKinds, TypeFamilies #-}
module Test where

import GHC.Exts  -- to get Constraint type constructor

class NextClass f where
    type Ctxt f :: Constraint
    next :: Ctxt f => f -> f

instance NextClass Int where
    type Ctxt Int = Num Int
    next b = b + 1

n :: (NextClass a) => a -> a
n v = next v

The next oddity is that `Int` already has a `Num` instance, so this isn't much of a constraint. But let's leave that aside for now (since it doesn't affect the error we get) and just look at the new error:

test.hs:15:7:
    Could not deduce (Ctxt a) arising from a use of `next'
    from the context (NextClass a)
      bound by the type signature for n :: NextClass a => a -> a
      at test.hs:15:1-12
    In the expression: next v
    In an equation for `n': n v = next v

Actually, this error looks quite sensible: the whole point of the constraint is that having an instance for `NextClass a` isn't enough; we must also have an instance of `Ctxt a`. So we can fix up the type signature:

n :: (NextClass a, Ctxt a) => a -> a
n v = next v

...and then it compiles. The final oddity is that this is a particularly degenerate use of constraint kinds, since this simpler code is essentially equivalent:

class NextClass f where
    next :: f -> f

instance Num Int => NextClass Int where
    next b = b + 1

...and the translation from the previous thing to the new thing is quite mechanical: instead of declaring `instance NextClass {- foo -} where type Ctxt {- foo -} = {- bar -}`, you just write `instance {- bar -} => NextClass {- foo -}` instead.

Problem

I'm starting to get my feet wet with the new class constraint extensions in GHC 7.4.2, but I am having some problems getting a small example to work. The code is as follows: ``` {-# LANGUAGE UndecidableInstances, MultiParamTypeClasses, KindSignatures, TypeFamilies, Rank2Types, ConstraintKinds, FlexibleInstances, OverlappingInstances #-} module Test where import GHC.Exts -- to get Constraint type constructor class NextClass f where type Ctxt f a :: Constraint next :: (Ctxt f a) => a -> a instance NextClass Int where type Ctxt Int a = Num a next b = b + 1 n :: (NextClass a) => a -> a n v = next v ``` What I want to do is define a `NextClass` type class, which will allow me to (given a value x) get the next value of x for all types that are instances of the `NextClass`. To use the `+` operator, I need the `Num a` class constraint for `Int`. However, GHC gives me the following error: ``` Could not deduce (Ctxt f0 a) arising from a use of `next' from the context (NextClass a) bound by the type signature for n :: NextClass a => a -> a In the expression: next v In an equation for `n': n v = next v ``` I suspect that GHC is telling me it does not have enough information to determine which constraint family instance to use. Could someone explain what I am doing wrong here. Is this a correct use of constraint families? TIA

Original source