What is the difference between the dot (.)
and the dollar sign ($)
?
As I understand it, they are both syntactic sugar for not needing to us
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)
Hope this helps!
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.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 ()
!
... 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
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 .
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.
(.)
, 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.
($)
, 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.
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
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.