This doc is for folks who come from languages with non-Haskell like ways of expressing type signatures. The Haskell folks might want to skip to the section where we talk aboutability requirements.

## Basic type signatures

We've seen basic type signatures in Unison before, when learning aboutdefining functions.As a brief review, the signature for`multiply`

below takes two`Nat`

'sas parameters and returns a`Nat`

.

```
multiply3 : Nat -> Nat -> Nat -> Nat
multiply3 a b c = a * b * c
```

Because functions arecurriedin Unison, the implied parentheses in the type signatures of a multi-parameter function are drawn like this:

```
multiply3 : Nat -> (Nat -> (Nat -> Nat))
multiply3 a b c = a * b * c
```

Notice how they all nest towards the right? The function arrow`->`

isright-associative.That means`multiply3`

is a function, which when given a`Nat`

,will return afunctionof`(Nat -> (Nat -> Nat))`

.

Remember when we said thatfunction applicationstarts at the leftmost element? This is the corollary to that in type signatures.

When you want to define a function with a different implied argument order than this, like when an argument is itself a function, use parentheses in your type signature.

Without the parentheses to designate the first argument as a function, this function would have four arguments of type`Nat`

.

## Type parameters

Thus far, we've been defining functions that have concrete types like`Text`

or`Bytes`

as their arguments. Unison functions can also use type parameters to represent functions that operate over many different types. We call these functions polymorphic. Type variables are introduced in a type signature withlower caseletters.

This is the implementation of`Function.id`

:

`Function.id : a -> a`

```
Function.id : a -> a
Function.id a = a
```

`Function.id`

contains a type parameter`a`

becauseany other typecan be assigned to that type variable and it will return a value of that specific type.`a`

can be a bound to a`Text`

when called with a text argument, as in`Function.id "hi"`

,or`a`

can be a`List`

of`Nat`

when called with a value like`Function.id [5, 4, 3]`

,etc, etc.

## Ability requirements

Let's take a closer look at the signature for`lib.base.data.List.map`

.In addition to the usual arguments,`(a -> b)`

and`[a]`

,you'll see`{𝕖}`

to the right side of the function arrows.

`lib.base.data.List.map : (a ->{𝕖} b) -> [a] ->{𝕖} [b]`

The`{e}`

is a generic ability requirement, we'll be talking aboutabilities in depth later,but for the purpose of reading Unison type signatures, the`{e}`

is a type variable which stands in for the set of possible effects a function can perform.

## All together now!

Take a look at the signature for`List.zipWith`

,we'll parse it together.

`List.zipWith : (a ->{𝕖} b ->{𝕖} c) -> [a] -> [b] ->{𝕖} [c]`

Here's some information we can glean from just the type signature:

`List.zipWith`

is polymorphic, we know this from the lowercase type parameters- It takes 3 arguments, the parentheses indicate the first is a function, the second is a list of type
`a`

and the third is a list of type`b`

- The "zipping" function provided as an argument has two parameters itself of type
`a`

and`b`

- The "zipping" function is permitted to perform effects, represented by the
`{e}`

- The return type of
`List.zipWith`

is a list of type`c`

--inthe process of returning that value, the overall function can perform effects.

### Where to next:

🌟Special operators for function application