
Patrick Redmond
Thank you both!
The key is that typeclasses are open. You could write a Fractional instance for (a -> a), in which case it would be possible to do _something_ with this code. Would it be useful? Even Haskell can't guarantee that.
Yes, this is important! Thanks.
Now, because we are writing ((+ 1) / 2) and we know that (/) takes two arguments that must be of the same type, we know that the type (Num a') => a' -> a' and the type (Num a'') => a'' have to be the same type, so it must be that a' = a -> a, so now we have:
(+ 1) :: (Num a, Num (a -> a)) => a -> a 2 :: (Num a, Num (a -> a)) => a -> a
I'm still a little confused here. How can passing "2" into "(+ 1) /" cause its type to be mangled? "2" has a type "(Num a) => a". How can the presence of "(+ 1)" force the type of "2" to suddenly accept an argument? How come it doesn't happen the other way around? (Meaning "2" forces the type of "(+ 1)" to become simply "(Num a) => a".)
Remember that in type signatures, "a" represents *any* type. And one example of a type that "a" can be is "b -> c", i.e. a function. The type isn't being mangled, it's being refined -- more information is being added. The type "a" doesn't say anything about arguments -- a value of type "a" might be a function, or it might not be. A value of type "a -> a" is definitely a function, so something has been learned about the type. And you can't go the other way (making (+ 1) go from type "a -> a" to just type "a") because that's throwing away information. -Keshav