Haskell and principal types

John Hughes rjmh@cs.chalmers.se
Sat, 6 Oct 2001 17:42:31 +0200 (MET DST)


	So here is the offending program:

	class IsNil a where
	  isNil :: a -> Bool

	instance IsNil [b] where
	  isNil [] = True
	  isNil _  = False

	f x y = let g = isNil
	         in (g x, g y)

	The monomorphism restriction applies to the binding of "g" since
	there is no type signature. Thus it is not legal to derive 
	"forall a . IsNil a => a -> Bool", but two legal possibilities are

	- forall b . [b] -> Bool, and
	- a -> Bool (without quantification and with "IsNil a" among the predicates).

	These two choices lead to different types for "f":

	- forall a b . [a] -> [b] -> (Bool,Bool), and
	- forall a . IsNil a => a -> a -> (Bool,Bool)

Interesting.

Every now and then I propagate for replacing the MR by two forms of binding:

       pat = expr    -- call by NAME binding, fully polymorphic and overloaded
       pat := expr   -- call by NEED binding, completely monomorphic

The point is to make the programmer aware of when monomorphism applies, so its
consequences are not surprising, and also aware (with an = binding) that there
is a risk of recomputation. It sounds as though Clean has adopted a similar
idea.

With "g = isNil", the type of f becomes

     forall a b. (IsNil a, IsNil b) -> a -> b -> (Bool, Bool)

With "g := isNil", it becomes

     forall a. IsNil a => a -> a -> (Bool, Bool)

The two incomparable types for f become types of two different programs;
problem solved (in this example at least).

Karl-Filip, would this idea restore the principal type property in general?

John Hughes