[Haskell] Re: Implicit type of numeric constants

Arie Peterson ariep at xs4all.nl
Wed Sep 20 08:35:55 EDT 2006


Hi Robert,


> I'm a newcomer to Haskell and I've been typing some simple
> expressions into Hugs in an attempt to understand how the built-in
> numeric types work . However, I'm puzzled by the following example:
>
> k = 2
>
> f :: Int -> Int -> Int
> f x y = x * y
>
> After loading a file containing this code into Hugs, if I type "f 2
> 2" I get the value 4 as expected, but if I type "f k k" I get a type
> error because the type of k is inferred to be Integer.
>
> This seems like a violation of referential transparency to me - I
> would expect the inferred type of k to be the same as the type of 2.

This is caused by a mechanism called "defaulting". See section 4.3.4 of
the Haskell report:
<http://haskell.org/onlinereport/decls.html#default-decls>.

In this case, the type of 'k' is defaulted to 'Integer'.

Basically, the problem this tries to solve is that if 'k' would have type
'(Num a) => a', then the expression 'show k' is ambiguous: the compiler
cannot decide what instance of 'Show' and 'Num' to use (and in this case
the string 'show k' actually depends on that choice: '2 :: Double' would
be shown as "2.0", '2 :: Integer' as "2".

You absolutely right about this defaulting breaking referential transparency.

> However, if I type an apparently equivalent let expression into Hugs
> directly, then I get the value 4 as expected
>
> let k = 2 ; f :: Int -> Int -> Int ; f x y = x * y in f k k
>
> Why is there a difference in behaviour?

Here, there is no defaulting, 'k' has the polymorphic type you expect, and
the use of 'k' as an argument to the monomorphically typed 'f' chooses the
right instance of 'Num'.

> For that matter, if the type of 2 is "Num a => a", which I understand
> to mean "an arbitrary numeric type", why is it OK to pass 2 to a
> function that expects an Int?

Well, "an arbitrary numeric type" in the sense "something of any numeric
type you may wish to ask for" (the implicit quantifier for 'a' is
universal, not existential). When using 'k', additional type constraints
(such as the monomorphic type of 'f') determine the choice of instance.


Greetings,

Arie


-- 

Mr. Pelican Shit may be Willy.

  ^
 /e\
 ---




More information about the Haskell mailing list