# Syntactic constructs

## Indentation¶

Haskell is indentation sensitive, like Python. Tabs or spaces are fine.

## Infixing and sections¶

Given a function `f`

, one can write it *infix* (i.e. in between its two arguments):

```
-- treating a prefix function as an infix function
> let subtract x y = x - y
> subtract 6 4
2
> 6 `subtract` 4
2
```

Functions whose names are symbols, like `+`

, `$`

and `.`

, are written infix by default. An order of precedence is defined, to avoid the need for bracketing. For example, `f a . f b`

means `(f a) . (f b)`

, and similarly, `f a $ f b`

means `(f a) $ (f b)`

.

For functions like `+`

or `/`

that are written by default *infix*, Haskell has some syntactic sugar to convert functions from infix to *prefix* (before their arguments):

```
-- treating an infix function as a prefix function
> 5 / 2
2.5
> (/) 5 2 -- (1)!
2.5
> (/) 2 5
0.4
> (/ 5) 2 -- (2)!
0.4
> (5 /) 2
2.5
```

- Whether infix or not, the type of
`(/)`

is`Double -> (Double -> Double)`

. - This is called a "section".

### Infixing in types¶

Similarly, `->`

is a *type-level* infix operation: `a -> b`

can be written `(->) a b`

.

As this suggests, `->`

is like `Either`

in that it is a function on types:

```
> :kind (->)
(->) :: * -> (* -> *)
> :kind (->) Bool
(->) Bool :: * -> *
> :kind (->) Bool Bool
(->) Bool Bool :: *
```

## Bracketing¶

Haskell tends to avoid brackets when possible.

Expressions like `4 * 3 + 5`

take a default bracketing (given when the operators were defined).

Functions application is left-associative:

`f x y z`

means`((f x) y) z`

`Either Bool Int`

means`(Either Bool) Int`

The `->`

type is right-associative:

`A -> B -> C -> D`

means`A -> (B -> (C -> D))`

### Dollar Sign¶

Code like the following is common in Haskell:

This is equivalent to:

Note

`$`

is just a regular function, used infix, and defined so that `f $ x = f x`

.

For more explanation, see: https://typeclasses.com/featured/dollar.

Dollars can be stacked:

means the same as:

Tip

Whenever you see a `$`

, read everything to the right as the input to what is on the left.

## Case-of¶

Here is an example of a `case _ of`

statement:

```
{-# LANGUAGE OverloadedStrings #-}
import Data.Text (Text)
data Color = Black | White
data Piece = Bishop Color | Knight Color | King Color
pieceToText :: ChessPiece -> Text
pieceToText (Piece _ color) = case color of
Black -> "black"
White -> "white"
```

This is a convenient way to pattern match.

## Guards¶

These are similar to `case`

statements, but instead of pattern matching, you give a boolean condition:

Note

`otherwise`

is not a keyword, in fact it is just the value `True`

:

For this reason, `otherwise`

will always satisfy the guard, and so is an appropriate catch-all final line.

## Let-in¶

Let-bindings may be recursive.

Hint

This gives an infinite list. You can sample from it as follows:

See the section on laziness for more information.

## Where¶

Similar to `let`

:

See here for differences .

## Do-notation¶

Do-notation is a syntax for imperative style programming. It can be used in conjunction with the IO type:

```
example :: IO ()
example = do
userInput <- getLine
let reversed = reverse userInput
writeFile "file/path" reversed
print reversed
```

Here, the order of operations is top-down (read line, write file, print), and the `<-`

arrow gives a name to the result of an operation (like `userInput`

, which is the result of reading from stdIn with `getLine`

) which can be used later.

Note

Do-notation gets converted in the following way:

Or for the above example:

As this shows, not only `IO`

, but any type `f :: * -> *`

which is an instance of `Monad`

(and thus implements `>>=`

) can be used with do-notation. For this reason, do-notation is common in Haskell code with many different `Monad`

instances.

Created: January 8, 2023