Andrew Coppin wrote:
 (id 'J', id True)   -- Works perfectly.

 \f -> (f 'J', f True)   -- Fails miserably.

Both expressions are obviously perfectly type-safe, and yet the type checker stubbornly rejects the second example. Clearly this is a flaw in the type checker.

When you type some expression such as

   \x -> x

you have to choose among an infinite number of valid types for it:

  Int -> Int
  Char -> Char
  forall a . a -> a
  forall a b . (a,b) -> (a,b)
  ...

Yet the type inference is smart enough to choose the "best" one:
   forall a. a -> a
because this is the "most general" type.

Alas, for code like yours:

  foo = \f -> (f 'J', f True)

there are infinite valid types too:

  (forall a. a -> Int) -> (Int, Int)
  (forall a. a -> Char)-> (Char, Char)
  (forall a. a -> (a,a)) -> ((Char,Char),(Bool,Bool))
  ...

and it is much less clear if a "best", most general type exists at all.
You might have a preference to type it so that

  foo :: (forall a . a->a) -> (Char,Bool)
  foo id ==> ('J',True) :: (Char,Bool)

but one could also require the following, similarly reasonable code to work:

  foo :: (forall a. a -> (a,a)) -> ((Char,Char),(Bool,Bool))
  foo (\y -> (y,y)) ==> (('J','J'),(True,True))
              :: ((Char,Char),(Bool,Bool))

And devising a type inference system allowing both seems to be quite hard. Requiring a type annotation for these not-so-common code snippets seems to be a fair compromise, at least to me.

Regards,
Zun.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to