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