[Haskell-cafe] Confusing type specialisation in ghci

Ryan Ingram ryani.spam at gmail.com
Mon Oct 8 13:40:50 EDT 2007


You can also remove the Monomorphism Restriction by adding an explicit
type signature:

Prelude> let sqlist :: Num a => [a] -> [a] ; sqlist = map sq
Prelude> :t sqlist
sqlist :: (Num a) => [a] -> [a]

Basically, there are three things that have to be the case for the MR
to kick in:
1) You are defining a function that takes no explicit arguments (or is
a pattern binding).
2) You didn't specify a type signature.
3) The inferred most-general-type of the function has typeclass constraints.

The reason becomes clear when you consider the following:

genericLength :: Num n => [a] -> n -- from Data.List

f :: [a] -> (Integer, Integer)
f xs = (len, len) where len = genericLength xs
(this example taken from
http://www.haskell.org/haskellwiki/Monomorphism_restriction)

Without the monomorphism restriction, len :: Num n2 => n2.  This means
len can't be calculated until you know its final type; it's
effectively stopped being a shared constant and started being a
function.  This means that when evaluating the pair (len,len), the
length of the list may end up being calculated twice!

With the monomorphism restriction, len gets the type Integer, and can be shared.

For contrast, consider this function:
f2 :: [a] -> (Int, Integer)
f2 xs = (len, len) where
    len :: Num n => n
    len = genericLength xs

In this case, you have no choice but to call genericLength twice,
since the result has to be two different types.

  -- ryan


More information about the Haskell-Cafe mailing list