If I do the following
functionS (x,y) = y
:t functionS
functionS :: (a, b) -> b
Now with this function:
functionC x y = if (x > y) then True else False
:t function
I would expect to get:
functionC :: (Ord a, Ord b) => a -> b -> Bool
But I get:
functionC :: Ord a => a -> a -> Bool
GHCI seems to be ok with the 2 previous results, but why does it give me the second? Why the type variable a AND b aren't defined?
I think you might be misreading type signatures. Through no fault of your own––the examples you using to inform your thinking are kind of confusing. In particular, in your tuple example
functionS :: (a,b) -> b
functionS (x,y) = y
The notation (_,_) means two different things. In the first line, (a,b) refers to a type, the type of pairs whose first element has type a and second has type b. In the second line, (x,y) refers to a specfiic pair, where x has type a and y has type b. While this "pun" provides a useful mnemonic, it can be confusing as you are first getting the hang of it. I would rather that the type of pairs be a regular type constructor:
functionS :: Pair a b -> b
functionS (x,y) = y
So, moving on to your question. In the signature you are given
functionC :: Ord a => a -> a -> Bool
a is a type. Ord a says that elements of the type a are orderable with respect to each other. The function takes two arguments of the same type. Some types that are orderable are Integer (numerically), String (lexicographically), and a bunch of others. That means that you can tell which of two Integers is the smaller, or which of two Strings are the smaller. However we don't necessarily know how to tell whether an Integer is smaller than a String (and this is good! Have you seen what kinds of shenanigans javascript has to do to support untyped equality? Haskell doesn't have to solve this problem at all!). So that's what this signature is saying –– there is only one single orderable type, a, and the function takes two elements of this same type.
You might still be wondering why functionS's signature has two different type variables. It's because there is no constraint confining them to be the same, such as having to order them against each other. functionS works equally well with a pair where both components are integers as when one is an integer and the other is a string. It doesn't matter. And Haskell always picks the most general type that works. So if they are not forced to be the same, they will be different.
There are more technical ways to explain all this, but I felt an intuitive explanation was in order. I hope it's helpful!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With