Cristiano Paris frodo at theshire.org
Thu Oct 8 06:29:44 EDT 2009

```On Thu, Oct 8, 2009 at 11:04 AM, minh thu <noteed at gmail.com> wrote:
> Hi,
>
> I'd like to know what are the typing rules used in Haskell (98 is ok).
>
> Specifically, I'd like to know what makes
>
> let i = \x -> x in (i True, i 1)
>
> legal, and not
>
> let a = 1 in (a + (1 :: Int), a + (1.0 :: Float))
>
> Is it correct that polymorphic functions can be used polymorphically
> (in multiple places) while non-functions receive a monomorphic type ?

First, "1" IS a constant function so it's in no way special and is a
value like any other.

That said, the type of 1 is (Num t) => t, hence polymorphic. But, when
used in the first element of the tuple, a is assigned a more concrete
type (Int) which mismatches with the second element of the tuple,
which is a Float.

If you swap the tuple, you'll find that the error reported by ghci is
the very same as before, except that the two types are swapped.

Is it possible to rewrite the expression so as to work? The answer is
yes, using existential quantification (and Rank2 polymorphism).

Here you are:
{-# LANGUAGE ExistentialQuantification, Rank2Types #-}
foo :: (forall a. (Num a) => a) -> (Int,Float)
foo = \x -> (x + (1 :: Int), x + (1 :: Float))

Hence:

foo 1 --> (2,2.0)

Bye,

Cristiano
```