6

Being a newbie to Haskell I can’t understand why the expression head . words “one two three four” throws an exception and function composition head . words must be applied with $ operator - the expression on the right of it doesn’t need further evaluation because it’s just a single String. The other way to compile it is to put head . words in parentheses but (head . words) :: String -> String has the same type as head . words :: String -> String so why putting it in parentheses makes the expression compile?

1 Answer 1

11

Because of precedence rules. Application has highest precedence; $ - lowest.

head . words “one two three four” is parsed as head . (words “one two three four”) i.e. words applied on a string must produce a function (as demanded by (.)). But that's not the type that words has:

Prelude> :t words
words :: String -> [String]

head . words $ “one two three four” on the other hand, is parsed as (head . words) “one two three four” and the types fit.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the answer, it was a bit difficult for me to grasp that the composition operator is itself a function.
@wojtek ah, yes, (.) :: (b -> c) -> (a -> b) -> a -> c. Don't forget, arrows in type signatures associate to the right. It's really (.) :: (b -> c) -> (a -> b) -> (a -> c). Imagine you've got these two pipes, g :: b->c and h :: a->b. So obviously, b output goes into the b input: (g.h)x = g (h x) i.e. (g.h) :: a->c.
@wojtek Every operator is itself a function, and has lower precedence than function application. This is something a Haskell programmer absolutely must keep in mind.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.