I am learning haskell at the moment and trying to figure out all the rules of prefix, infix, precedence, etc.
While trying to implement a function which appends two lists and sorts them I started with:
appendAndSort :: [a] -> [a] -> [a]
appendAndSort = sort . (++)
which does no compile.
Following:
appendAndSort :: Ord a => [a] -> [a] -> [a]
appendAndSort = (sort .) . (++)
on the other hand does work.
Why do I have to add a second dot at sort and parentheses around it?
The expression
(f . g) xmeansf (g x).Coherently,
(f . g) x ymeansf (g x) y.Note how
yis passed as a second parameter tof, not tog. The result is notf (g x y).In your case,
(sort . (++)) x ywould meansort ((++) x) y, which would callsortwith first argument(++) x(the function which prepends the listxto its list argument), and with second argumenty. Alas, this is ill-typed sincesortonly takes one argument.Consequently, this is also invalid
hence so is this
By contrast,
((f .) . g) x ydoes work as expected. Let's compute:So this really makes
yto be passed tog(and notf).In my opinion the "idiom"
(f .) . gisn't worth using. The pointful\x y -> f (g x y)is much simpler to read, and not terribly longer.If you really want, you can define a custom composition operator to handle the two-argument case.
Then, you can write