
Andrew Coppin wrote:
What a perplexing example! :-}
For a bit less mind-boggling example, try meditating about the next two functions. It may be instructive to comment out type signatures and see what happens. {-# OPTIONS -fglasgow-exts #-} foo :: (forall a . a -> a) -> (Bool, String) foo g = (g True, g "bzzt") bar :: (forall a . Num a => a) -> (Integer, Float) bar x = (x `div` 3, x / 3) In a nutshell, rank-N typing is simple. Rank-1 polymorphism allows us to type functions like map, foldr etc we all know and love. Rank-1 polymorphic types contain type variables that may be instantiated with any monomorphic type (e.g., Int, String, etc). Rank-2 polymorphic functions accept rank-1 polymorphic values as argument. Rank-N polymorphic functions accept rank-(N-1) polymorphic values as argument. As a practical example of the need for higher-rank polymorphism you may want to read about ST monad.