I'm reading a book Haskell Programming From First Principles. On p. 122 authors highlight fst
function:
fst :: (a, b) -> a
The result of the function, which has type
a
. It’s the samea
that was in the tuple(a, b)
. How do we know it’s the samea
? We can say that we know the input typea
and the output typea
must be the same type, and we can see that nothing happens between the input and the output; that is, there is no operation that comes between them that could transform thata
into some other value of that type.
Also earlier, p. 107, in reference to fst
and snd
:
The type signature tells us there’s nothing those functions could do other than return the first or second value, respectively.
I don't get this. If a
had a typeclass constraint like Num a => (a, b) -> a
the function could easily add 3 to the first argument of the tuple and return something of the same type a
but a different value, and this would not show up in the type signature of the function. Is the point that you couldn't really do anything to the input tuple without some typeclass constraint? Or without knowing that the input is e.g. a list, as in tail :: [a] -> [a]
, by which we just know based on our knowledge of lists that tail
could be adding or removing elements to/from the input? Even without a typeclass constraint, couldn't (a, b) -> a
just return some arbitrary constant of type a
, not necessarily the first element in the tuple?
How do the authors come to this conclusion?