When you are new to haskell, the weird looking operators might get you puzzled. In this blog post i will explain two basic ones the $ and .. They are used to specify in which order haskell should try to evaluate a bunch of functions.

Let's say you have two functions for operating on strings

trim :: String -> String
upperFirst :: String -> String

and a userInput :: String which comes from the console or a webinterface. We will used these functions to trim off the excess white space and then capitalize the first character. How they work is not important here, only that they take a string and return a string.

Associativity

You probably know haskell can chain functions, so your first initial thought would be to write

result = upperFirst trim userInput

This will evaluate as

result = (upperFirst trim) userInput

Which will not work because upperFirst expects a string as it's first argument and not a function. This is due to associativity, which can be either left or right. Since we are trying to "give arguments to functions", or more commonly described as "applying the function to it's argument", we are talking about function application. For which the associativity is left. That means if you have a function (trim), and to the left of that is another function (upperFirst) haskell tries the left function first.

To fix this we can just put the parenthesis in the right place ourselves

result = upperFirst (trim userInput)

Precendence

Another important concept in haskell is precedence. We say if something is more important to evaluate first then it has higher precedence. Just like in 2 + 3 * 4 the * has higher precedence and thus should be evaluated first even though it's on the right side.

Normal function application has the highest precedence of 10. You can use ghci to get information precedence.

prelude> :i ($)
infixr 0 $
prelude> :i (.)
infixr 9 .

note: some extra information given was left out

We see that both $ and . have lower precedence than normal (10). $ is even extremely low (0). This becomes important going into the next sections.

$

(low-precedence) function application

$ is a shorthand to evaluate stuff on the right first is $. Operators are also functions in haskell and so this operator has a function definition

($) :: (a -> b) -> a -> b

Since this function (operator) is used between (infix) two other things, this might be more clear

(a -> b) $ a

First comes a function a -> b that takes a value that is on the right side of $. Using $ we can rewrite the string functions as

result = upperFirst $ trim userInput

trim userInput is evaluated first into a and then given to (a -> b) (upperFirst).

$ is called (low-precedence) function application because everything to the left and right gets evaluated first. If it had higher precedence we would have to write

(function here) $ (value here)

Which would make the $ redundant.

.

function composition

The . can be used to compose function together. Thus with . we can make a new function, like so

prettify = upperFirst . trim

now you can do

result = prettify userInput

However there are a couple of important things to note about ..

. evaluation

Firstly you might think you can use . directly like so

result = upperFirst . trim userInput

This doesn't work because . has less precedence than normal function application. So in effect this would evaluate as

result = upperFirst . (trim userInput)

. is given a string as it's second argument. While it's function signature is

(.) :: (b -> c) -> (a -> b) -> a -> c

and this expects a function instead ((a -> b)). The right thing to write would be

result = (upperFirst . trim) userInput
-- or
result = upperFirst . trim $ userInput

pointfree style

That . function signature might look pretty complicated. Can you find all the mentioned arguments in the code? Maybe not, and this is because that function composition was written in pointfree style. Pointfree has nothing to do with . directly, it just so happens that a pointfree function often use .. Note that the point in pointfree does NOT refer to the . operator.

This is a pointfree function

prettify = upperFirst . trim

Then what's the not-pointfree "normal" variant? Well it's this

prettify x = (upperFirst . trim) x

Now we can find everything back from the . function signature

(.) :: (b -> c) -> (a -> b) -> a -> c

-- upperFirst is used for b -> c
-- trim       is used for a -> b
-- x          is used for a
-- and of course  c  is the value you get when you run prettify

Without the . we would have to write this function as

prettify x = upperFirst (trim x)

which is about just as much typing as with using .. Only you can not reduce this further to pointfree without . in this case.

We can say that . can help make code shorter, but this pointfree style also can make your code harder to understand. When you are starting out in haskell you should know what . does, but at the same time do not try to go overboard and use it everywhere. It's important that your code stays very readable. Maybe in time you will get used to the . operator and you prefer to use it more often.

I will leave you with an example from the haskell wiki pointfree page which shows it's not required to use . to make a pointfree function.

sum = foldr (+) 0