Re: [Haskell-beginners] A few really short beginners questions

Thank You very much for the fast replies! I think I expressed myself
badly in the first question. What does not work is the following:
class Test a
instance Num a => Test a
Thanks, fweth
2010/10/3, Brent Yorgey
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 _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On 10/03/10 14:39, Klaus Gy wrote:
Thank You very much for the fast replies! I think I expressed myself badly in the first question. What does not work is the following:
class Test a
instance Num a => Test a
For a reason that seems pretty odd until you get used to it. In the instance, "Test a", or the "a" thereof, is called the "instance head". "Num a" is called the "context". When the compiler looks for an instance, it works by looking just at the "instance head": and "a" refers to all types. "instance Num a => Test a" says that the one and only instance that the class has is the one described in that instance. (And it only works when "a" is a Num type; for other attempted uses you'd get a compile error.) For various reasons, such instances aren't allowed by default. Note that instance Num a => Test [a] might also mean something different than you intended, even though it's allowed: it defines the one and only instance of Test on lists. -Isaac

2010/10/3, Isaac Dupree
On 10/03/10 14:39, Klaus Gy wrote:
Thank You very much for the fast replies! I think I expressed myself badly in the first question. What does not work is the following:
class Test a
instance Num a => Test a
For a reason that seems pretty odd until you get used to it. In the instance, "Test a", or the "a" thereof, is called the "instance head". "Num a" is called the "context". When the compiler looks for an instance, it works by looking just at the "instance head": and "a" refers to all types. "instance Num a => Test a" says that the one and only instance that the class has is the one described in that instance. (And it only works when "a" is a Num type; for other attempted uses you'd get a compile error.) For various reasons, such instances aren't allowed by default.
Note that instance Num a => Test [a] might also mean something different than you intended, even though it's allowed: it defines the one and only instance of Test on lists.
-Isaac
Thanks! I could have avoided this question because I've just found out that the details of instance declarations are all described in the Haskell 98 report along with other restrictions I was not aware of. So, can I assume that there is no need in praxis to declare all instances of an existing class to instances of a new class? fweth

On Mon, Oct 04, 2010 at 12:05:55AM +0200, Klaus Gy wrote:
2010/10/3, Isaac Dupree
: On 10/03/10 14:39, Klaus Gy wrote:
Thank You very much for the fast replies! I think I expressed myself badly in the first question. What does not work is the following:
class Test a
instance Num a => Test a
For a reason that seems pretty odd until you get used to it. In the instance, "Test a", or the "a" thereof, is called the "instance head". "Num a" is called the "context". When the compiler looks for an instance, it works by looking just at the "instance head": and "a" refers to all types. "instance Num a => Test a" says that the one and only instance that the class has is the one described in that instance. (And it only works when "a" is a Num type; for other attempted uses you'd get a compile error.) For various reasons, such instances aren't allowed by default.
Note that instance Num a => Test [a] might also mean something different than you intended, even though it's allowed: it defines the one and only instance of Test on lists.
-Isaac
Thanks! I could have avoided this question because I've just found out that the details of instance declarations are all described in the Haskell 98 report along with other restrictions I was not aware of. So, can I assume that there is no need in praxis to declare all instances of an existing class to instances of a new class?
No, this is a reasonable thing to do sometimes. As the error message says, if you want to enable this you can turn on the FlexibleInstances flag (either by passing -XFlexibleInstances to the compiler, or by putting {-# LANGUAGE FlexibleInstances #-} at the top of your program). -Brent
participants (3)
-
Brent Yorgey
-
Isaac Dupree
-
Klaus Gy