I am currently trying to wrap my head around typeclasses and instances and I don't quite understand the point of them yet. I have two questions on the matter so far:
1) Why is it necessary to have a type class in a function signature when the function uses some function from that type class. Example:
f :: (Eq a) => a -> a -> Bool
f a b = a == b
Why put (Eq a)
in the signature. If ==
is not defined for a
then why not just throw the error when encountering a == b
? What is the point in having to declare the type class ahead?
2) How are type classes and function overloading related?
It is not possible to do this:
data A = A
data B = B
f :: A -> A
f a = a
f :: B -> B
f b = b
But it is possible to do this:
data A = A
data B = B
class F a where
f :: a -> a
instance F A where
f a = a
instance F B where
f b = b
What is up with that? Why can't I have two functions with the same name but operating on different types... Coming from C++ I find that very strange. But I probably have wrong conceptions about what these things really are. but once I wrap them in these type class instance thingies I can.
Feel free to hurl category or type theoretical words at me as well, as I am learning about these subjects in parallel to learning Haskell and I suspect there is a theoretical basis in these for how Haskell does things here.
f :: a -> a -> Bool
, and later apply it to something that can't be compared for equality, say,f (1+) (1-)
, how should the compiler detect that we now need to have an(==)
defined in order to throw an error? Answer: the compiler records a small fact aboutf
that it applies(==)
to its arguments, so that it knows when it sees calls tof
to check that(==)
is available. How do we notate that fact? Answer: we put it in the type, asf :: Eq a => a -> a -> Bool
. – Daniel Wagner