Consider:
λ :type (+) @Integer
(+) @Integer :: Integer -> Integer -> Integer
λ :type (\x y -> x + y) @Integer
...
...error...
...Cannot apply expression...
...
λ f = (+)
λ :type f @Integer
...
...error...
...Cannot apply expression...
...
λ g = \x y -> x + y
λ :type g @Integer
...
...error...
...Cannot apply expression...
...
λ h x y = x + y
λ :type h @Integer
...
...error...
...Cannot apply expression...
...
At the same time:
λ :type (+)
... :: Num a => a -> a -> a
λ :type (\x y -> x + y)
... :: Num a => a -> a -> a
λ :type f
... :: Num a => a -> a -> a
λ :type g
... :: Num a => a -> a -> a
λ :type h
... :: Num a => a -> a -> a
So, even though there is no distinction in the type of these objects, they appear as distinct to the type application.
In most cases type applications can only be applied when there is an explicit type signature. Quoting the GHC documents:
If the function is an identifier (the common case), its type is considered known only when the identifier has been given a type signature.
Why?
I'd guess that design exists because the order of type variables is well defined when you have explicit signatures.
Am I missing something obvious?
Up to you how obvious the above is. You can dig thought both the docs and the design discussion to see the evolution of the conversation but order of arguments, when type application can only be done strictly by the order, seems to jump out as an issue.
Is this a bug?
I don't believe so. Perhaps for the lambda case.
Is this a feature?
A feature in so far as consistency is good.
Is this poor language design? Is this great language design?
Perhaps a better language design is to allow simple examples, such as yours, to work when there are no possible ambiguities (the type argument order is implicit by virtue of there only being one type argument).
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