Cheatsheet: Rank 2 types with typeclasses in Haskell

Posted on July 8, 2017

Here’s a brief example of rank-2 polymorphism in Haskell.

{-# LANGUAGE Rank2Types #-}

data Number = FloatVal Float | IntVal Int
            deriving (Show)

applyFn :: (forall a. (Num a) => a -> a -> a)
           -> Number -> Number -> Either String Number
applyFn f (IntVal l)   (IntVal r)   = Right $ IntVal   $ f l r
applyFn f (FloatVal l) (FloatVal r) = Right $ FloatVal $ f l r
applyFn _ _            _            = Left "Mismatch"

example = applyFn (+) (IntVal 1) (IntVal 2)

The key parts are the flag enabling the Rank2Types compiler feature:

{-# LANGUAGE Rank2Types #-}

and the portion of the type signature dealing with the input function f:

(forall a. (Num a) => a -> a -> a)

It is key that the forall a. (and the typeclass (Num a)) are inside the input function type, rather that part of the type of applyFn.