Cannot remove an argument (Point-free style Haskell) - haskell

I am having a problem with removing an argument 'e' in this function:
numocc e = map length . (map . filter . (==)) e
The function checks the number of occurences of an element inside a two-dimensional list (lists within list). So you call it as follows:
numocc 1 [[1, 2], [2, 3, 2, 1, 1], [3]]
Result : [1,2,0]
Argument e is on the far right on both sides of the equal sign, and is not encased in any parameters. Therefore, I should be able to remove it to get a point-free function:
numocc = map length . (map . filter . (==))
However I get this error:
Type error in application
Expression : map length . map . filter . (==)
Term : map length
Type : [[b]] -> [Int]
Does not match : ([[a]] -> [[a]]) -> [Int]
What is the problem here? Thanks.

Your original function is being parsed as
numocc e = (map length) . ((map . filter . (==)) e)
So you can't just remove the e since it doesn't technically appear at the end of the definition. However, if you define the operator
(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.:) = (.) . (.)
Then you can write it as
numocc = map length .: (map . filter . (==))
The parentheses on map . filter . (==) are required since you can't mix . and .: due to fixity rules.
However, at this point you're just making this function harder to read and maintain. It would be better to break it down into smaller sections and introduce some intermediate names, along with adding the right type signature and giving the function a better name to start with:
numOccurrences :: Eq a => a -> [a] -> Int
numOccurrences valueToCount values = length (filter (== valueToCount) values)
numOccurrencesInSublists :: Eq a => a -> [[a]] -> [Int]
numOccurrencesInSublists valueToCount = map (numOccurrences valueToCount)
This is far more readable, doesn't rely on fancy operators, and expresses your intent more clearly. Since the case for counting in a single list is a separate function, you can now use it elsewhere too.
Remember, elegant code isn't about making it as short as possible, it's about making it as clear as possible. Descriptive names (not necessarily long ones), explicit arguments, and small, composable units are best.

Related

groupBy-like function such that the binary predicate holds between consecutive elements of each group instead of any two

On Hackage I see that groupBy's implementation is this:
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy eq (x:xs) = (x:ys) : groupBy eq zs
where (ys,zs) = span (eq x) xs
which means that the predicate eq holds between any two elements of each group. Examples:
> difference_eq_1 = ((==1).) . flip (-)
> first_isnt_newline = ((/= '\n').) . const
>
> Data.List.groupBy difference_eq_1 ([1..10] ++ [11,13..21])
[[1,2],[3,4],[5,6],[7,8],[9,10],[11],[13],[15],[17],[19],[21]]
>
> Data.List.groupBy first_isnt_newline "uno\ndue\ntre"
["uno\ndue\ntre"]
What if instead I want to group elements such that the predicate holds between any pair of consecutive elements, so that the above results would be as follows?
[[1,2,3,4,5,6,7,8,9,10,11],[13],[15],[17],[19],[21]]
["uno\n","due\n","tre"]
I wrote it myself, and it looks a bit ugly
groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy' p = foldr step []
where step elem [] = [[elem]]
step elem gs'#((g'#(prev:g)):gs)
| elem `p` prev = (elem:g'):gs
| otherwise = [elem]:gs'
So I was wandering if such a function exists already and I just don't find it.
As regards the second usage, Data.List.groupBy first_isnt_newline, where the binary predicate basically ignores the second argument and applies a unary predicate to the first, I've just found that Data.List.HT.segmentAfter unary_predicate does the job, where unary_predicate is the negation of the unary predicate in which const's output is forwarded. In other words Data.List.groupBy ((/= '\n').) . const === Data.List.HT.segmentAfter (=='\n').
There is a groupBy package that does exactly that.
But here’s another way of implementing it:
Zip the list with its tail to test the predicate on adjacent elements
Generate a “group index” by scanning the result and incrementing the group whenever the predicate is false
Group by the index
Remove the indices
groupByAdjacent :: (a -> a -> Bool) -> [a] -> [[a]]
groupByAdjacent p xs
= fmap (fmap fst)
$ groupBy ((==) `on` snd)
$ zip xs
$ scanl' (\ g (a, b) -> if p a b then g else succ g) 0
$ zip xs
$ drop 1 xs
For an input like [1, 2, 3, 10, 11, 20, 30], the predicate will return [True, True, False, True, False, False] and the resulting group indices will be [0, 0, 0, 1, 1, 2, 3].
The scan can also be written pointfree as scanr (bool succ id . uncurry p) 0, since the scan direction doesn’t matter (although the group indices will be reversed). The group index might be handy or just more readable to keep as an integer, but it could be a Bool instead, because the minimum size of a group is 1: the functional argument of the scan would be bool not id . uncurry p, which can be simplified to (==) . uncurry p. And several of these parts could be factored into reusable functions, like zipNext = zip <*> drop 1, but I’ve inlined them for simplicity’s sake.

Difficulty understanding the below function in haskell [duplicate]

What is the difference between the dot (.) and the dollar sign ($)?
As I understand it, they are both syntactic sugar for not needing to use parentheses.
The $ operator is for avoiding parentheses. Anything appearing after it will take precedence over anything that comes before.
For example, let's say you've got a line that reads:
putStrLn (show (1 + 1))
If you want to get rid of those parentheses, any of the following lines would also do the same thing:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
The primary purpose of the . operator is not to avoid parentheses, but to chain functions. It lets you tie the output of whatever appears on the right to the input of whatever appears on the left. This usually also results in fewer parentheses, but works differently.
Going back to the same example:
putStrLn (show (1 + 1))
(1 + 1) doesn't have an input, and therefore cannot be used with the . operator.
show can take an Int and return a String.
putStrLn can take a String and return an IO ().
You can chain show to putStrLn like this:
(putStrLn . show) (1 + 1)
If that's too many parentheses for your liking, get rid of them with the $ operator:
putStrLn . show $ 1 + 1
They have different types and different definitions:
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
infixr 0 $
($) :: (a -> b) -> a -> b
f $ x = f x
($) is intended to replace normal function application but at a different precedence to help avoid parentheses. (.) is for composing two functions together to make a new function.
In some cases they are interchangeable, but this is not true in general. The typical example where they are is:
f $ g $ h $ x
==>
f . g . h $ x
In other words in a chain of $s, all but the final one can be replaced by .
Also note that ($) is the identity function specialised to function types. The identity function looks like this:
id :: a -> a
id x = x
While ($) looks like this:
($) :: (a -> b) -> (a -> b)
($) = id
Note that I've intentionally added extra parentheses in the type signature.
Uses of ($) can usually be eliminated by adding parenthesis (unless the operator is used in a section). E.g.: f $ g x becomes f (g x).
Uses of (.) are often slightly harder to replace; they usually need a lambda or the introduction of an explicit function parameter. For example:
f = g . h
becomes
f x = (g . h) x
becomes
f x = g (h x)
($) allows functions to be chained together without adding parentheses to control evaluation order:
Prelude> head (tail "asdf")
's'
Prelude> head $ tail "asdf"
's'
The compose operator (.) creates a new function without specifying the arguments:
Prelude> let second x = head $ tail x
Prelude> second "asdf"
's'
Prelude> let second = head . tail
Prelude> second "asdf"
's'
The example above is arguably illustrative, but doesn't really show the convenience of using composition. Here's another analogy:
Prelude> let third x = head $ tail $ tail x
Prelude> map third ["asdf", "qwer", "1234"]
"de3"
If we only use third once, we can avoid naming it by using a lambda:
Prelude> map (\x -> head $ tail $ tail x) ["asdf", "qwer", "1234"]
"de3"
Finally, composition lets us avoid the lambda:
Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"
The short and sweet version:
($) calls the function which is its left-hand argument on the value which is its right-hand argument.
(.) composes the function which is its left-hand argument on the function which is its right-hand argument.
One application that is useful and took me some time to figure out from the very short description at Learn You a Haskell: Since
f $ x = f x
and parenthesizing the right hand side of an expression containing an infix operator converts it to a prefix function, one can write ($ 3) (4 +) analogous to (++ ", world") "hello".
Why would anyone do this? For lists of functions, for example. Both:
map (++ ", world") ["hello", "goodbye"]
map ($ 3) [(4 +), (3 *)]
are shorter than
map (\x -> x ++ ", world") ["hello", "goodbye"]
map (\f -> f 3) [(4 +), (3 *)]
Obviously, the latter variants would be more readable for most people.
Haskell: difference between . (dot) and $ (dollar sign)
What is the difference between the dot (.) and the dollar sign ($)?. As I understand it, they are both syntactic sugar for not needing to use parentheses.
They are not syntactic sugar for not needing to use parentheses - they are functions, - infixed, thus we may call them operators.
Compose, (.), and when to use it.
(.) is the compose function. So
result = (f . g) x
is the same as building a function that passes the result of its argument passed to g on to f.
h = \x -> f (g x)
result = h x
Use (.) when you don't have the arguments available to pass to the functions you wish to compose.
Right associative apply, ($), and when to use it
($) is a right-associative apply function with low binding precedence. So it merely calculates the things to the right of it first. Thus,
result = f $ g x
is the same as this, procedurally (which matters since Haskell is evaluated lazily, it will begin to evaluate f first):
h = f
g_x = g x
result = h g_x
or more concisely:
result = f (g x)
Use ($) when you have all the variables to evaluate before you apply the preceding function to the result.
We can see this by reading the source for each function.
Read the Source
Here's the source for (.):
-- | Function composition.
{-# INLINE (.) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)
And here's the source for ($):
-- | Application operator. This operator is redundant, since ordinary
-- application #(f x)# means the same as #(f '$' x)#. However, '$' has
-- low, right-associative binding precedence, so it sometimes allows
-- parentheses to be omitted; for example:
--
-- > f $ g $ h x = f (g (h x))
--
-- It is also useful in higher-order situations, such as #'map' ('$' 0) xs#,
-- or #'Data.List.zipWith' ('$') fs xs#.
{-# INLINE ($) #-}
($) :: (a -> b) -> a -> b
f $ x = f x
Conclusion
Use composition when you do not need to immediately evaluate the function. Maybe you want to pass the function that results from composition to another function.
Use application when you are supplying all arguments for full evaluation.
So for our example, it would be semantically preferable to do
f $ g x
when we have x (or rather, g's arguments), and do:
f . g
when we don't.
... or you could avoid the . and $ constructions by using pipelining:
third xs = xs |> tail |> tail |> head
That's after you've added in the helper function:
(|>) x y = y x
My rule is simple (I'm beginner too):
do not use . if you want to pass the parameter (call the function), and
do not use $ if there is no parameter yet (compose a function)
That is
show $ head [1, 2]
but never:
show . head [1, 2]
A great way to learn more about anything (any function) is to remember that everything is a function! That general mantra helps, but in specific cases like operators, it helps to remember this little trick:
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
and
:t ($)
($) :: (a -> b) -> a -> b
Just remember to use :t liberally, and wrap your operators in ()!
All the other answers are pretty good. But there’s an important usability detail about how ghc treats $, that the ghc type checker allows for instatiarion with higher rank/ quantified types. If you look at the type of $ id for example you’ll find it’s gonna take a function whose argument is itself a polymorphic function. Little things like that aren’t given the same flexibility with an equivalent upset operator. (This actually makes me wonder if $! deserves the same treatment or not )
The most important part about $ is that it has the lowest operator precedence.
If you type info you'll see this:
λ> :info ($)
($) :: (a -> b) -> a -> b
-- Defined in ‘GHC.Base’
infixr 0 $
This tells us it is an infix operator with right-associativity that has the lowest possible precedence. Normal function application is left-associative and has highest precedence (10). So $ is something of the opposite.
So then we use it where normal function application or using () doesn't work.
So, for example, this works:
λ> head . sort $ "example"
λ> e
but this does not:
λ> head . sort "example"
because . has lower precedence than sort and the type of (sort "example") is [Char]
λ> :type (sort "example")
(sort "example") :: [Char]
But . expects two functions and there isn't a nice short way to do this because of the order of operations of sort and .
I think a short example of where you would use . and not $ would help clarify things.
double x = x * 2
triple x = x * 3
times6 = double . triple
:i times6
times6 :: Num c => c -> c
Note that times6 is a function that is created from function composition.

Haskell: Explanation of function syntax

In this custom made version of the map function, there is an "f" is a few spots. I'm not sure what the f means in the function (I'm a beginner in Haskell). Is it something to do with higher order functions? Can someone explain what f means and then explain what the actual function is doing to create the map functionality?
map f [] = []
map f (a:b) = f a:map f b
f is a function that is a parameter of the map function since map has the following type:
map :: (a -> b) -> [a] -> [b]
That it is, a function from a to b and a list of elements of type a and then using the function passed as the first parameter to convert the list (passed as second parameter) in a list of element of type b by using the function (passed as first parameter)
This function is very useful for traversing a list applying a function.
Let's say I have a list of numbers
For example:
[2,3,4,5]
If i want to add 1 to each element of the list I could use map as following:
map (+1) [2,3,4,5]
Or if you prefer the lambda use:
map (\x -> x+1) [2,3,4,5]
And we'll get as an answer:
[3,4,5,6]
So in the implementation of map
map f [] = []
map f (a:b) = f a:map f b
We can see that the f is this function that is used to transform the list by applying it to each element of the list
The implementation is recursive goes until the end of the list converting element by element and appending them to the list so the list has the same order as before the function was applied.
In your map definition, f is the first argument you're supplying to it. Your first pattern match could also be defined with a lambda to denote where the parameter is coming from:
map f [] = -- ...
map \f -> \[] -> -- ...
In the second definition, you're recursing down the contents of the (:) pattern match:
map f (x:xs) = (f x) : (map f xs)
I'm applying f to the first element we see x, then prepending that result to the recursed call of map through the rest of xs.

Error when trying to use function composition in Haskell

I have just began recently to learn Haskell, more specifically on the topics of function composition, partial functions, maps, filters and sectioning. On one of the exercises am asked to modify the twoFilters function by using function composition.
I have read a few wikis on . but am having quite a hard time getting it to work correctly. As i understand it, it works by performing the functions b . a on alphabetical order and returning the result. In other words x = foo a and then foo b of x. However after applying several "variations/possibilities" with the bellow two filters functions i cant get it to compile due to errors.
greaterThanOne :: Int -> Bool
greaterThanOne = (>1)
lessThanTen :: Int -> Bool
lessThanTen = (<10)
twoFilters :: [Int] -> [Int]
twoFilters xs= filter lessThanTen (filter greaterThanOne xs)
These two being the unsuccessful attempts I had most confidence on;
twoFilters xs = filter (lessThanTen . greaterThanOne xs)
twoFilters xs = filter (lessThanTen xs . greaterThanOne xs)
Where on the reasoning am I going wrong?
The attempts you were confident about are a simple failure in your logic: the dot operator works like this:
(f.g)(x) = f(g(x))
So, trying to compute an example of 5 gives:
lessThanThen(greaterThanOne(5)) = lessThanTen(True) -- that can't be right, can it???
What you want is a lambda and &&:
filter (\x-> (lessThanThen x) && greaterThanOne(x))
Alternatively, you can use two filters:
filter lessThanTen . filter greaterThanOne $
Enter the wonderful world of Applicative Functors:
import Control.Applicative
greaterThanOne = (>1)
lessThanTen = (<10)
twoFilters = filter ((&&) <$> greaterThanOne <*> lessThanTen)
twoFilters [1,2,3,4,5,6,7,8,9,10]
-- [2,3,4,5,6,7,8,9]
Read Learn you a Haskell - Applicative Functors for a detailed explanation.
You can't compose those two functions like this. f . g works like composition in maths, i.e. is equivalent to f(g(x)). That means the outer function must take an argument of a type that inner function returns, in your case the outer function would have to be Bool -> Bool.
You can write your twoFilters using composition operator like this:
twoFilters = (filter lessThanTen) . (filter greaterThanOne)
(.) expects a function which takes one argument and returns a value, but you pass it a Bool value in:
lessThanTen . greaterThanOne xs
which is wrong.
Here:
lessThanTen xs . greaterThanOne xs
you're trying to compose two Bool values, but you should've composed two functions which return Bool values.
One issue it that function application has highest precedence. So lessThanTen . greaterThanOne xs tries to compose lessThanTen with the result of greaterThanOne xs (which doesn't work to start with, the function works on integers, not on lists thereof). Likewise, lessThanTen xs. greaterThanOne xs tries to compose the results of those function calls (assuming they'd make sense in the first place), not the functions themself.
Another problem is a misunderstanding of . - (f . g) x is equivalent to f (g x), i.e. the result of the first function is the argument for the second. So the type of g must be (a -> b) and the type of f must be (b -> c) (both b are the same type variable!). What you want to apply both functions to the same argument and join the results with &&. There's no existing functions for this as far as I know (at least Hoogle didn't find anything for (a -> Bool) -> (a -> Bool) -> a -> Bool). You'll have to make your own:
both f g x = f x && g x
Alternatively, you coudl just stick to filtering twice (which isn't as bad as it sounds thanks to lazy evaluation) - filter (>1) $ filter (<10) xs.
As i understand it, it works by performing the functions b . a on alphabetical order and returning the result. In other words x = foo a and then foo b of x
This could be written in Haskell as
let x = foo a in
foo b x
(where does foo come from?) but the correct
(b . a) x = let y = a x in
b y
Or, shorter:
(b . a) x = b (a x)
Now, filter lessThanTen (filter greaterThanOne xs) has a similar shape to the right side of this definition, if you remember you could write it as (filter lessThanTen) ((filter greaterThanOne) xs):
((filter lessThanTen) . (filter greaterThanOne)) xs
Presumably what you actually want is filter ??? xs, but that should be enough to go on with.
You have it almost right. I find the easiest way to start learning function composition with . is to use $ first instead.
So you have a list
twoFilters xs = xs
You want to filter by greaterThanOne
twoFilters xs = filter greaterThanOne $ xs
You additionally want to filter by lessThanTen
twoFilters xs = filter lessThanTen $ filter greaterThanOne $ xs
Now move from left to right, replacing all $s with . except for the last $
twoFilters xs = filter lessThanTen . filter greaterThanOne $ xs
You could use parenthesis instead of $ now:
twoFilters xs = (filter lessThanTen . filter greaterThanOne) xs
Or just define the function pointfree:
twoFilters = filter lessThanTen . filter greaterThanOne
The parenthesized version is the most important, I think. It shows that you fuse the two partially-applied functions filter lessThanTen and filter greaterThanOne into one mega-filtering function, with . and then you apply the list to it. You need to parenthesize them because . binds less tightly than function application via whitespace (space can be considered an uber-high-fixity version of $). Remember, when you use ., you are fusing two functions together to form one mega-function.
It is relevant to inspect the type signature of .
(.) :: (b -> c) -> (a -> b) -> a -> c
The functions you feed it have to "line up" with very particular type signatures (they have to be compatible for fusing). But honestly, the key is learning to recognize when function application (with space) is binding more tightly than you intend and messing up the type signatures of functions you are trying to compose. That's how it was for me, anyways.

What is the difference between . (dot) and $ (dollar sign)?

What is the difference between the dot (.) and the dollar sign ($)?
As I understand it, they are both syntactic sugar for not needing to use parentheses.
The $ operator is for avoiding parentheses. Anything appearing after it will take precedence over anything that comes before.
For example, let's say you've got a line that reads:
putStrLn (show (1 + 1))
If you want to get rid of those parentheses, any of the following lines would also do the same thing:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
The primary purpose of the . operator is not to avoid parentheses, but to chain functions. It lets you tie the output of whatever appears on the right to the input of whatever appears on the left. This usually also results in fewer parentheses, but works differently.
Going back to the same example:
putStrLn (show (1 + 1))
(1 + 1) doesn't have an input, and therefore cannot be used with the . operator.
show can take an Int and return a String.
putStrLn can take a String and return an IO ().
You can chain show to putStrLn like this:
(putStrLn . show) (1 + 1)
If that's too many parentheses for your liking, get rid of them with the $ operator:
putStrLn . show $ 1 + 1
They have different types and different definitions:
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
infixr 0 $
($) :: (a -> b) -> a -> b
f $ x = f x
($) is intended to replace normal function application but at a different precedence to help avoid parentheses. (.) is for composing two functions together to make a new function.
In some cases they are interchangeable, but this is not true in general. The typical example where they are is:
f $ g $ h $ x
==>
f . g . h $ x
In other words in a chain of $s, all but the final one can be replaced by .
Also note that ($) is the identity function specialised to function types. The identity function looks like this:
id :: a -> a
id x = x
While ($) looks like this:
($) :: (a -> b) -> (a -> b)
($) = id
Note that I've intentionally added extra parentheses in the type signature.
Uses of ($) can usually be eliminated by adding parenthesis (unless the operator is used in a section). E.g.: f $ g x becomes f (g x).
Uses of (.) are often slightly harder to replace; they usually need a lambda or the introduction of an explicit function parameter. For example:
f = g . h
becomes
f x = (g . h) x
becomes
f x = g (h x)
($) allows functions to be chained together without adding parentheses to control evaluation order:
Prelude> head (tail "asdf")
's'
Prelude> head $ tail "asdf"
's'
The compose operator (.) creates a new function without specifying the arguments:
Prelude> let second x = head $ tail x
Prelude> second "asdf"
's'
Prelude> let second = head . tail
Prelude> second "asdf"
's'
The example above is arguably illustrative, but doesn't really show the convenience of using composition. Here's another analogy:
Prelude> let third x = head $ tail $ tail x
Prelude> map third ["asdf", "qwer", "1234"]
"de3"
If we only use third once, we can avoid naming it by using a lambda:
Prelude> map (\x -> head $ tail $ tail x) ["asdf", "qwer", "1234"]
"de3"
Finally, composition lets us avoid the lambda:
Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"
The short and sweet version:
($) calls the function which is its left-hand argument on the value which is its right-hand argument.
(.) composes the function which is its left-hand argument on the function which is its right-hand argument.
One application that is useful and took me some time to figure out from the very short description at Learn You a Haskell: Since
f $ x = f x
and parenthesizing the right hand side of an expression containing an infix operator converts it to a prefix function, one can write ($ 3) (4 +) analogous to (++ ", world") "hello".
Why would anyone do this? For lists of functions, for example. Both:
map (++ ", world") ["hello", "goodbye"]
map ($ 3) [(4 +), (3 *)]
are shorter than
map (\x -> x ++ ", world") ["hello", "goodbye"]
map (\f -> f 3) [(4 +), (3 *)]
Obviously, the latter variants would be more readable for most people.
Haskell: difference between . (dot) and $ (dollar sign)
What is the difference between the dot (.) and the dollar sign ($)?. As I understand it, they are both syntactic sugar for not needing to use parentheses.
They are not syntactic sugar for not needing to use parentheses - they are functions, - infixed, thus we may call them operators.
Compose, (.), and when to use it.
(.) is the compose function. So
result = (f . g) x
is the same as building a function that passes the result of its argument passed to g on to f.
h = \x -> f (g x)
result = h x
Use (.) when you don't have the arguments available to pass to the functions you wish to compose.
Right associative apply, ($), and when to use it
($) is a right-associative apply function with low binding precedence. So it merely calculates the things to the right of it first. Thus,
result = f $ g x
is the same as this, procedurally (which matters since Haskell is evaluated lazily, it will begin to evaluate f first):
h = f
g_x = g x
result = h g_x
or more concisely:
result = f (g x)
Use ($) when you have all the variables to evaluate before you apply the preceding function to the result.
We can see this by reading the source for each function.
Read the Source
Here's the source for (.):
-- | Function composition.
{-# INLINE (.) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)
And here's the source for ($):
-- | Application operator. This operator is redundant, since ordinary
-- application #(f x)# means the same as #(f '$' x)#. However, '$' has
-- low, right-associative binding precedence, so it sometimes allows
-- parentheses to be omitted; for example:
--
-- > f $ g $ h x = f (g (h x))
--
-- It is also useful in higher-order situations, such as #'map' ('$' 0) xs#,
-- or #'Data.List.zipWith' ('$') fs xs#.
{-# INLINE ($) #-}
($) :: (a -> b) -> a -> b
f $ x = f x
Conclusion
Use composition when you do not need to immediately evaluate the function. Maybe you want to pass the function that results from composition to another function.
Use application when you are supplying all arguments for full evaluation.
So for our example, it would be semantically preferable to do
f $ g x
when we have x (or rather, g's arguments), and do:
f . g
when we don't.
... or you could avoid the . and $ constructions by using pipelining:
third xs = xs |> tail |> tail |> head
That's after you've added in the helper function:
(|>) x y = y x
My rule is simple (I'm beginner too):
do not use . if you want to pass the parameter (call the function), and
do not use $ if there is no parameter yet (compose a function)
That is
show $ head [1, 2]
but never:
show . head [1, 2]
A great way to learn more about anything (any function) is to remember that everything is a function! That general mantra helps, but in specific cases like operators, it helps to remember this little trick:
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
and
:t ($)
($) :: (a -> b) -> a -> b
Just remember to use :t liberally, and wrap your operators in ()!
All the other answers are pretty good. But there’s an important usability detail about how ghc treats $, that the ghc type checker allows for instatiarion with higher rank/ quantified types. If you look at the type of $ id for example you’ll find it’s gonna take a function whose argument is itself a polymorphic function. Little things like that aren’t given the same flexibility with an equivalent upset operator. (This actually makes me wonder if $! deserves the same treatment or not )
The most important part about $ is that it has the lowest operator precedence.
If you type info you'll see this:
λ> :info ($)
($) :: (a -> b) -> a -> b
-- Defined in ‘GHC.Base’
infixr 0 $
This tells us it is an infix operator with right-associativity that has the lowest possible precedence. Normal function application is left-associative and has highest precedence (10). So $ is something of the opposite.
So then we use it where normal function application or using () doesn't work.
So, for example, this works:
λ> head . sort $ "example"
λ> e
but this does not:
λ> head . sort "example"
because . has lower precedence than sort and the type of (sort "example") is [Char]
λ> :type (sort "example")
(sort "example") :: [Char]
But . expects two functions and there isn't a nice short way to do this because of the order of operations of sort and .
I think a short example of where you would use . and not $ would help clarify things.
double x = x * 2
triple x = x * 3
times6 = double . triple
:i times6
times6 :: Num c => c -> c
Note that times6 is a function that is created from function composition.

Resources