**View and edit this tutorial on Github** | Discuss on Reddit | Tweet this

One aspect of Haskell that many new users find difficult to get a
handle on is *operators*. Unlike many other languages, Haskell gives a
lot of flexibility to developers to define custom operators. This can
lead to shorter, more elegant code in many cases. For example, compare
these three equivalent pieces of code:

v1 = mappend (mappend "hello " "there ") "world" v2 = "hello " `mappend` "there " `mappend` "world" v3 = "hello " ++ "there " ++ "world"

Unfortunately, not all operators are as self-explanatory as the `++`

operator (which, in case you're wondering, is "list append"). This
page will attempt to cover the most common "surprising" operators. In
other words: we won't bother covering common mathematical operators
like `+`

or `*`

, nor will we cover operators defined in less common
libraries.

It's worth pointing out as well that for many operators, using the
Hoogle search engine can be a
great way to find out about an operator, or for that matter *any*
function. It's
pretty easy to find `++`

that way. Go ahead, try it out now!

`$`

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

One of the most common operators, and source of initial confusion, is
the `$`

operator. All this does is *apply a function*. So, `f $ x`

is
exactly equivalent to `f x`

. If so, why would you ever use `$`

? The
primary reason is - for those who prefer the style - to avoid
parentheses. For example, you can replace:

foo (bar (baz bin))

with

foo $ bar $ baz bin

A less common but arguably more compelling use case is to capture the act of applying a function to an argument. To clarify that rather vague statement with an example:

#!/usr/bin/env stack -- stack --resolver ghc-7.10.3 runghc double :: Int -> Int double x = x + x square :: Int -> Int square x = x * x main :: IO () main = print (map ($ 5) [double, square])

The `($ 5)`

bit means "apply the function to 5", and then we can use
`map`

to use it with both the `double`

and `square`

functions.

`.`

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

Not much more to it than that: take two functions and compose them together.

#!/usr/bin/env stack -- stack --resolver ghc-7.10.3 runghc double :: Int -> Int double x = x + x square :: Int -> Int square x = x * x main :: IO () main = (print . double . square) 5

Or you can combine this together with the `$`

operator to avoid those
parentheses if you're so inclined:

main = print . double . square $ 5

In addition to its usage for function composition, the period is also used for hierarchical modules, e.g.:

#!/usr/bin/env stack -- stack --resolver ghc-7.10.3 runghc import qualified Data.Monoid main :: IO () main = putStrLn $ Data.Monoid.mappend "hello " "world"

Finally, in the `Control.Category`

module, the `Category`

typeclass
*also* uses the `.`

operator to define categorical composition. This
generalizes standard function composition, but is not as commonly
used.

`&`

(&) :: a -> (a -> b) -> b

`&`

is just like `$`

only backwards. Take our example for `$`

:

foo $ bar $ baz bin

This is semantically equivalent to:

bin & baz & bar & foo

`&`

is useful because the order in which functions are applied to their
arguments read left to right instead of the reverse (which is the case
for `$`

). This is closer to how English is read so it can improve code clarity.

In our function composition example we composed the functions
`square`

, `double`

, and `print`

and applied the resulting function to the number `5`

.

Rewriting it using `&`

gives us

#!/usr/bin/env stack -- stack --resolver lts-6.4 runghc import Data.Function double :: Int -> Int double x = x + x square :: Int -> Int square x = x * x main :: IO () main = 5 & square & double & print

`<>`

(<>) :: Monoid m => m -> m -> m

The `<>`

operator is just a synonym for the
`mappend`

function. This
comes from the `Monoid`

typeclass, which represents types which have
an identity and an associative binary operation. Some examples:

- For lists,
`<>`

is the same as`++`

(append two lists) - For vectors, this logic holds as well
- For
`Set`

s, this is a union operation (all values present in either`Set`

) - For
`Map`

s, we have a "left biased union", meaning we combine the key/value pairs from both inputs, and if both inputs share a key, the value in the left input is selected - For numbers, both addition and multiplication form a
`Monoid`

, where 0 is the additive identity (since`0 + x = x`

) and 1 is the multiplicative identity (since`1 * x = x`

). Therefore, to avoid confusion,`Data.Monoid`

defines helper newtype wrappers`Sum`

and`Product`

#!/usr/bin/env stack -- stack --resolver lts-6.4 runghc import Data.Monoid ((<>)) main :: IO () main = putStrLn $ "hello " <> "there " <> "world!"

`<$>`

(<$>) :: Functor f => (a -> b) -> f a -> f b (<$) :: Functor f => a -> f b -> f a ($>) :: Functor f => f a -> b -> f b

The `<$>`

operator is just a synonym for the
`fmap`

function
from the `Functor`

typeclass. This function generalizes the `map`

function for lists to many other data types, such as `Maybe`

, `IO`

,
and `Map`

.

#!/usr/bin/env stack -- stack --resolver ghc-7.10.3 runghc import Data.Monoid ((<>)) main :: IO () main = do putStrLn "Enter your year of birth" year <- read <$> getLine let age :: Int age = 2020 - year putStrLn $ "Age in 2020: " <> show age

In addition, there are two additional operators provided which replace
a value inside a `Functor`

instead of applying a function. This can be
both more convenient in some cases, as well as for some `Functor`

s be
more efficient. In terms of definition:

value <$ functor = const value <$> functor functor $> value = const value <$> functor x <$ y = y $> x x $> y = y <$ x

`<*>`

(<*>) :: Applicative f => f (a -> b) -> f a -> f b (*>) :: Applicative f => f a -> f b -> f b (<*) :: Applicative f => f a -> f b -> f a

Commonly seen with `<$>`

, `<*>`

is an operator that applies a wrapped
function to a wrapped value. It is part of the `Applicative`

typeclass, and is very often seen in code like the following:

foo <$> bar <*> baz

For cases when you're dealing with a `Monad`

, this is equivalent to:

do x <- bar y <- baz return (foo x y)

Other common examples including parsers and serialization libraries. Here's an example you might see using the aeson package:

data Person = Person { name :: Text, age :: Int } deriving Show -- We expect a JSON object, so we fail at any non-Object value. instance FromJSON Person where parseJSON (Object v) = Person <$> v .: "name" <*> v .: "age" parseJSON _ = empty

To go along with this, we have two helper operators that are less frequently used:

`*>`

ignores the value from the first argument. It can be defined as:a1 *> a2 = (id <$ a1) <*> a2

Or in

`do`

-notation:a1 *> a2 = do _ <- a1 a2

For

`Monad`

s, this is completely equivalent to`>>`

.`<*`

is the same thing in reverse: perform the first action then the second, but only take the value from the first action. Again, definitions in terms of`<*>`

and`do`

-notation:(<*) = liftA2 const a1 <* a2 = do res <- a1 _ <- a2 return res

(>>=) :: Monad m => m a -> (a -> m b) -> m b (=<<) :: Monad m => (a -> m b) -> m a -> m b (>>) :: Monad m => m a -> m b -> m b (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c) (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)

There are a few different monadic binding operators. The two most
basic are `>>=`

and `>>`

, as they can be trivially expressed in
`do`

-notation. And as previously mentioned, `>>`

is just a synonym for
`*>`

from the `Applicative`

class, so it's even easier. `=<<`

is
just `>>=`

with the arguments reversed.

m1 >>= f = do x <- m1 f x m1 >> m2 = do _ <- m1 m2 f =<< m1 = do x <- m1 f x

In addition to these two operators, there are also composition
operators for when you have two monadic functions. `>=>`

pipes the
result from the left side to the right side, while `<=<`

pipes the
result the other way. In other words:

f >=> g = \x -> do y <- f x g y g <=< f = \x -> do y <- f x g y f >=> g = g <=< f g >=> f = f <=< g

`<|>`

(<|>) :: Alternative f => f a -> f a -> f a

The `Alternative`

typeclass provides a binary operation on applicative
functors (`<|>`

), as well as some identity value (`empty`

). This is
used in the ecosystem for a number of different activities, e.g.:

- In parser libraries for defining different alternative parsing options
- In the async library to run two different
`Concurrently`

actions at once and take the first result to succeed

#!/usr/bin/env stack -- stack --resolver lts-6.4 runghc --package async import Control.Applicative ((<|>)) import Control.Concurrent (threadDelay) import Control.Concurrent.Async (Concurrently (..)) main :: IO () main = do res <- runConcurrently $ (Concurrently (threadDelay 1000000 >> return (Left "Hello"))) <|> (Concurrently (threadDelay 2000000 >> return (Right 42))) print res

If you're aware of other common operators that cause confusion, please open an issue or a PR to extend this document!