Search code examples
haskelltype-signature

Giving function type signature inside typeclass instance gives an error


Once I have successfully solved an exercise for Functor typeclass:

data ExactlyOne a = ExactlyOne a deriving (Eq, Show)

instance Functor ExactlyOne where
  (<$>) ::
    (a -> b)
    -> ExactlyOne a
    -> ExactlyOne b
  (<$>) f a = ExactlyOne $ f (runExactlyOne a)

Solving another exercise I needed to define Enum typeclass functions for a custom Odd type.

data Odd = Odd Integer
  deriving (Eq, Show)

instance Enum Odd where
  -- succ :: Odd -> Odd <-- error
  succ (Odd x) = Odd $ x + 2

Now when I try to specify the type signature for a simpler function, ghci gives an error:

Illegal type signature in instance declaration: succ :: Odd -> Odd (Use InstanceSigs to allow this)

It works without it, but I wonder why is this error produced and how to specify the type signature correctly for this function?


Solution

  • The signature in the instances would be redundant to the type signature in the type classes. If you later slightly change the signature of the typeclass, for example by adding an extra type constraint, it could result in errors simply because the signatures are no longer in harmony.

    This is specified in the section on Instance Declarations in the Haskell '10 report:

    The declarations may not contain any type signatures or fixity declarations, since these have already been given in the class declaration. As in the case of default class methods (Section 4.3.1), the method declarations must take the form of a variable or function definition.

    The Enum typeclass [src] already contains the signature:

    class  Enum a   where
        -- | the successor of a value.  For numeric types, 'succ' adds 1.
        succ                :: a -> a
        -- ...

    If you however want to specify the signature, you can turn on the InstanceSigs language extension [ghc-doc], like:

    {-# LANGUAGE InstanceSigs #-}
    
    data Odd = Odd Integer deriving (Eq, Show)
    
    instance Enum Odd where
      succ :: Odd -> Odd
      succ (Odd x) = Odd $ x + 2