Dear Arie,

Thank you for your answers to my questions - I'd spotted the section on ambiguous types and defaults in the language manual, but I hadn't appreciated that it might be applicable in this situation because I didn't know that show and read could be applied to (almost) all types.

However, I still think there's a bit of an inconsistency here. I understand that if k had the type "Num a => a", then the expression "show k" would be ambiguous, but unless I write that expression, there's no ambiguity...

So it seems to me that the type checker is being a bit too eager to prevent something that hasn't happened yet.

In contrast, in the case where I write "let k = 2 ...", the type checker seems happy to resolve the polymorphic type within the context of the let expression, and does what I expect.

So is the problem that the context is effectively unbounded when I load the definition from a file, and hence the type checker has to be very conservative about preventing the ambiguity?

I'm afraid I'm also still not clear about why 2 doesn't default to 2::Integer in the same way that k defaults to k::Integer, but that's probably because I don't understand polymorphic types properly yet.

Thanks again,

Robert

On 20 Sep 2006, at 13:35, Arie Peterson wrote:

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\
 ---



_______________________________________________
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell

Reply via email to