[Haskell-cafe] Vanishing polymorphism
Tom Schrijvers
Tom.Schrijvers at cs.kuleuven.be
Wed May 9 03:27:44 EDT 2007
>
> To cut a long story short, could someone explain why:
>
>> :t negate
> negate :: forall a. (Num a) => a -> a
>
>> :t let f (fn :: forall a . Num a => a -> a) r s = (fn r, fn s) in f negate
> let f (fn :: forall a . Num a => a -> a) r s = (fn r, fn s) in f negate
> :: forall r s. (Num r, Num s) => r -> s -> (r, s)
>
> but
>
>> :t let f r s = (return negate) >>= (\fn -> return (fn r, fn s)) in f
> let f r s = (return negate) >>= (\fn -> return (fn r, fn s)) in f
> :: forall a (m :: * -> *). (Num a, Monad m) => a -> a -> m (a, a)
>
> and
>
>> :t let f r s = (return negate) >>= (\(fn::forall n . (Num n) => n -> n) -> return (fn r, fn s)) in f
>
> <interactive>:1:35:
> Couldn't match expected type `a -> a'
> against inferred type `forall n. (Num n) => n -> n'
> In the pattern: fn :: forall n. (Num n) => n -> n
> In a lambda abstraction:
> \ (fn :: forall n. (Num n) => n -> n) -> return (fn r, fn s)
> In the second argument of `(>>=)', namely
> `(\ (fn :: forall n. (Num n) => n -> n) -> return (fn r, fn s))'
>
> I.e. why does the polymorphism get destroyed?
Unless annotated otherwise, functions destroy the polymorphism of their
arguments.
In your first example f's argument is annotated to be
polymorphic, hence you can call it with two different types.
In your second example, the lambda abstraction does not declare it expects
a polymorphic argument. So you get a monomorhpic one. Neither does return
or >>=. So that all works fine.
In your third example, return destroys the polymorphism of negate. becomes
monomorphic for some a, the a -> a without forall. >>= is happy with the
monomorphism. Then it is received by the lambda abstraction that expects a
polymorphic type and causes the error.
You can read more about this in the paper:
Practical type inference for arbitrary-rank types
Simon Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, and Mark Shields
http://research.microsoft.com/~simonpj/papers/higher-rank/index.htm
Basically, it comes down to the fact that preserving polymorphism is too
hard for type inference, unless you the prorgrammer provide
sufficient declarations for it.
Cheers,
Tom
--
Tom Schrijvers
Department of Computer Science
K.U. Leuven
Celestijnenlaan 200A
B-3001 Heverlee
Belgium
tel: +32 16 327544
e-mail: tom.schrijvers at cs.kuleuven.be
More information about the Haskell-Cafe
mailing list