Possible Duplicate:
Haskell: difference between . (dot) and $ (dollar sign)
I understand that "$" binds an expression like "f1 (f2 x)" to a simpler form "f1 $ f2 x". How does "f1.f2 x" differ from this?
Possible Duplicate:
Haskell: difference between . (dot) and $ (dollar sign)
I understand that "$" binds an expression like "f1 (f2 x)" to a simpler form "f1 $ f2 x". How does "f1.f2 x" differ from this?
Well, f1 . f2 x
is the composition of f1
and f2 x
. You probably mean (f1 . f2) x
or, equivalently, f1 . f2 $ x
; i.e. the composition of f1
and f2
, applied to x
.
The answer can be found by looking at the types:
($) :: (a -> b) -> a -> b
(.) :: (b -> c) -> (a -> b) -> a -> c
Simply, ($)
applies a function to its argument,1 and (.)
composes its two arguments. The two chains
f . g . h $ x
and
f $ g $ h $ x
are equivalent; the former is generally preferred because it's easier to refactor the composition out into its own function with cut-and-paste, but this isn't a universal preference. It's also a bit lower on visual noise.
1 Indeed, ($)
is identical to id
, the identity function; it just returns the function it's given. It's only useful because of the very low operator precedence (the lowest, in fact) given to it.
Neither ($)
nor (.)
are doing anything special to "bind an expression". They're just operators like any other. All you need to know are what they're defined as, and what their fixities are. For the first:
infixr 0 $
f $ x = f x
So it's function application, with a very low precedence and right-associativity. So if you have f x $ g y z
that means (f x) (g y z)
which is equivalent to just f x (g y z)
. It's used to avoid parentheses, mostly.
For the second:
infixr 9 .
(.) f g x = f (g x)
This looks similar at first, but (.)
is operating on two functions, not a function and an argument, and has very high precedence. So if you have (f x . g y) z
that means (f x) ((g y) z)
which is equivalent to just f x (g y z)
.
The key difference is that with (.)
you can chain many functions together, like f1 . f2 . f3
, whereas with ($)
you can only apply more functions to a result. So in an expression like f x $ g y $ h z
, if you decide you want to replace a single value z
with a whole list of values, you can't just write map (f x $ g y $ h) zs
because there's nothing for the functions to be applied to in the parenthesized expression. If you instead write something like f x . g y . h $ z
, you can remove just the final function application and get map (f x . g y . h) zs
and it will work.