You have it almost right. I find the easiest way to start learning functional composition with . is to use $ first.
So you have a list
twoFilters xs = xs
You want to filter with greaterThanOne
twoFilters xs = filter greaterThanOne $ xs
You also want to filter by lessThanTen
twoFilters xs = filter lessThanTen $ filter greaterThanOne $ xs
Now move from left to right, replacing all $ with . except last $
twoFilters xs = filter lessThanTen . filter greaterThanOne $ xs
Now you can use brackets instead of $ :
twoFilters xs = (filter lessThanTen . filter greaterThanOne) xs
Or just define a pointfree function:
twoFilters = filter lessThanTen . filter greaterThanOne
The staple-dependent version is the most important, I think. It shows that you are fusing two partially applied functions filter lessThanTen and filter greaterThanOne into one megafiltration function c . and then you apply a list to it. You need to bracket them because . binds less tightly than the application function through whitespace (a space can be considered a version of $ with a high degree of reliability). Remember that when you use . , you combine two functions together to form one megafunction.
It is important to verify the type signature .
(.) :: (b -> c) -> (a -> b) -> a -> c
The functions that you feed it must "line up" with very specific type signatures (they must be compatible for merging). But to be honest, the key is to learn to recognize when the application (the space) is associated more closely than you expect and mess up the types of function signatures that you are trying to create. One way or another, it was for me.
source share