[Haskell-cafe] Ambiguous type signature in class declaration

Benjamin Franksen benjamin.franksen at bessy.de
Wed Apr 27 16:12:44 EDT 2005


On Wednesday 27 April 2005 19:12, Bo Herlin wrote:
> I am trying to make a class like this:
>  > class CRank a b where
>  >   rank :: a -> b -> Maybe Integer -- Nothing means b is out of range
>
> or badly constructed
>
>  >   unrank :: a -> Integer -> Maybe b -- Nothing means rank is out of
>  > range count :: a -> Maybe Integer -- Nothing means infinity
>
> but all i get is
>
> ERROR "./Cafe.lhs":8 - Ambiguous type signature in class declaration
> *** ambiguous type : CRank a b => a -> Maybe Integer
> *** assigned to    : count

The type variable 'b' does not appear on the right side of the '=>' in the 
type of 'count'. The compiler complains about an 'ambigous type signature', 
because the type of 'b', and hence of 'count', cannot be determined from its 
arguments. Thus, if there are instances

  instance CRank Prime Integer where ...
  instance CRank Prime Int where ...

then these would have different implementations for 'count'. Which one should 
be chosen if you write

  count Prime

the infinite result for Integers or the (presumably) finite result for Ints? 

Functional dependencies only help if you never want to declare both of the 
above instances. If this is not the case (and therefore you don't want to use 
a fundep 'a -> b'), you can disambiguate the signature by giving it a second 
(phantom) argument to indicate the type:

class CRank a b where
  ...
  count :: a -> b -> Maybe Integer
    -- implementations must not evaluate 2nd argument

and call it like this

  let n = count Prime (undefined::Integer)

Admittedly, the extra argument is not very nice and neither is the 
'undefined'. Another trick is to split the class:

  class Countable a where
    count :: a -> Maybe Integer -- Nothing means infinity

  class Countable a => CRank a b where
    rank :: ...
    ...

Ben


More information about the Haskell-Cafe mailing list