
Hi! I have a few questions to improve my knowledge of Haskell. I didn't stumble over these problems while working on specific tasks, I more or less constructed them explicitly to get an adequate understanding of the basic Haskell semantics. 1 Why can't I apply a class directly to all instances of another, existing class? For example why is it possible to write class Test a instance Num a => Test [a] but not with instance Num a => Test a in the last row? 2 Why is the following example not valid? f :: a -> a f '0' = 0 f x = 1 I think the reason lies in the type system but I can't locate it exactly. 3 Why is the following legal [] :: Num a => [a] but not with a self declared class instad of Num (unresolved overloading)? 4 Why does in the declaration f undefined = '0' the expression undefined work apparently in the same way as a wildcard? Thanks, fweth

On Sun, Oct 03, 2010 at 08:00:19PM +0200, Klaus Gy wrote:
Hi! I have a few questions to improve my knowledge of Haskell. I didn't stumble over these problems while working on specific tasks, I more or less constructed them explicitly to get an adequate understanding of the basic Haskell semantics.
1
Why can't I apply a class directly to all instances of another, existing class? For example why is it possible to write
class Test a
instance Num a => Test [a]
but not with
instance Num a => Test a
in the last row?
Because these two instances are overlapping: if an instance for Test [Int] was wanted, which instance should be chosen? Both 'Test [a]' and 'Test a' match 'Test [Int]' so it is ambiguous. Now, it is possible to turn on the OverlappingInstances flag, in which case the 'more specific' instance (in this case Test [a]) would be chosen, but this is generally considered bad for your health unless you Know What You Are Doing (tm).
2
Why is the following example not valid?
f :: a -> a f '0' = 0 f x = 1
I think the reason lies in the type system but I can't locate it exactly.
There is no type information around at runtime, so if f is supposed to work for all types it must work *uniformly* for all types: it is not possible to say "if the argument is a Char, do this; otherwise, do that".
3
Why is the following legal
[] :: Num a => [a]
but not with a self declared class instad of Num (unresolved overloading)?
It should be possible with a self declared class. I'd have to see more context to see why you are getting this error.
4
Why does in the declaration
f undefined = '0'
the expression undefined work apparently in the same way as a wildcard?
In a pattern, names simply match anything and bind that name to the value. The fact that you have used the name "undefined" is not relevant; it simply shadows any existing binding for the name "undefined". So f blergh = '0' is precisely the same as f undefined = '0' Also, consider this example: x = 6 f x = 3 f _ = 9 At first glance you might think that f yields 3 when passed 6 as an argument and 9 for everything else; but in fact f always returns 3; the two x's have nothing to do with one another. -Brent

On Sun, Oct 03, 2010 at 08:00:19PM +0200, Klaus Gy wrote:
Hi! I have a few questions to improve my knowledge of Haskell. I didn't stumble over these problems while working on specific tasks, I more or less constructed them explicitly to get an adequate understanding of the basic Haskell semantics.
I'm fairly noobish at haskell, but I can answer some of them I think. [...]
2
Why is the following example not valid?
f :: a -> a f '0' = 0 f x = 1
I think the reason lies in the type system but I can't locate it exactly.
in the type declaration, you have claimed that f takes an object of one type and returns another object of that same type. That is, every instance of 'a' in the type declaration has to refer to the *same* type. 'a' gets bound to a specific type and must match that type throughout. now, f '0' = 0 has type f::Num t => Char -> t. This means that f takes a char and returns some numeric type. But char is not an instance of Num, and so this definition of f does not match its type signature.
3
Why is the following legal
[] :: Num a => [a]
but not with a self declared class instad of Num (unresolved overloading)?
there was a discussion here over the last few days about the polymorphism of []. It might help to read over that.
4
Why does in the declaration
f undefined = '0'
the expression undefined work apparently in the same way as a wildcard?
I believe that what you are doing here is binding the argument of f to a local name "undefined". You are subsequently not using the argument to f, so it is ignored giving a wildcard type of behavior. If this was included in a list of pattern-matching definitions of f, then it will match when all others fail. But this is not a property of "undefined" in this context. You've just given it a name that happens to coincide with a reserved word. You could just as easily use "x" or "foo" or whatever in the same way. Note that commonly, if you are not going to use the argument to a function, you use "_" to prevent it from being bound at all. for example, in: f:: Int -> Char f 1 = '1' f 2 = '2' f undefined = '0' -- using your word here, but I'd typically not since its a reserved word you could replace "undefined" with "_" f _ = '0' to get the same result. The first usage will generate a compiler warning for the unused binding. The second will not. At least that's how I understand it. A

On Sun, Oct 03, 2010 at 11:11:47AM -0700, Andrew Sackville-West wrote:
Why is the following example not valid?
f :: a -> a f '0' = 0 f x = 1
I think the reason lies in the type system but I can't locate it exactly.
in the type declaration, you have claimed that f takes an object of one type and returns another object of that same type. That is, every instance of 'a' in the type declaration has to refer to the *same* type. 'a' gets bound to a specific type and must match that type throughout.
now, f '0' = 0 has type f::Num t => Char -> t. This means that f takes a char and returns some numeric type. But char is not an instance of Num, and so this definition of f does not match its type signature.
This is a good point, I hadn't even noticed the type mismatch! However, note that this isn't the whole story: f :: a -> a f '0' = 'a' f x = x does not work either, for the reasons I mentioned in my other email. -Brent

On Sunday 03 October 2010 20:11:47, Andrew Sackville-West wrote:
But this is not a property of "undefined" in this context. You've just given it a name that happens to coincide with a reserved word. You could just as easily use "x" or "foo" or whatever in the same way. Note that commonly, if you are not going to use the argument to a function, you use "_" to prevent it from being bound at all.
Minor correction, "undefined" is not a reserved word (like e.g. "data" is), it is just a variable (or name) bound in the Prelude. You can shadow predefined names like undefined, otherwise etc., but not reserved words, so f data = 3 won't compile while f undefined = 3 will.

On Mon, Oct 04, 2010 at 02:08:08PM +0200, Daniel Fischer wrote:
On Sunday 03 October 2010 20:11:47, Andrew Sackville-West wrote:
But this is not a property of "undefined" in this context. You've just given it a name that happens to coincide with a reserved word. You could just as easily use "x" or "foo" or whatever in the same way. Note that commonly, if you are not going to use the argument to a function, you use "_" to prevent it from being bound at all.
Minor correction, "undefined" is not a reserved word (like e.g. "data" is), it is just a variable (or name) bound in the Prelude. You can shadow predefined names like undefined, otherwise etc., but not reserved words, so
f data = 3
won't compile while
f undefined = 3
will.
Thanks! A
participants (4)
-
Andrew Sackville-West
-
Brent Yorgey
-
Daniel Fischer
-
Klaus Gy