Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions src/content/docs/syntax/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@ title: Functions
description: Functions in Gren
---

A function returns different values depending on its input. In Gren, a function will always return the same result if provided the same input.
If constants allow you to give a name to a value, a function allows you to give a name to a calculation that produces a value. Functions take one or more inputs and return a single value.

```elm
addOne number =
number + 1
```

`addOne` is the name of the function and it is defined as being `number + 1`. If you do something like `result = addOne 7` then `result` will equal 8.

Very importantly, in Gren, a function will always return the same result if provided the same input. This might seem obvious for something like `addOne` but it's also true of things such as updating a complex bit of state in an application or even making a HTTP request. We'll get into how Gren accomplishes this in a later section, for now it's enough just to know that Gren makes the guarantee that given the same input to a function, you will always get the same result.

Ok now let's see what a function that has more than one argument looks like.

```elm
sumOf first second =
Expand All @@ -13,9 +24,9 @@ sumOfFiveAndTwo =
sumOf 5 2
```

Here, `sumOf` is the name of the function, while `first` and `second` are the inputs to the function. The return value of `sumOf` is the last computed expression. In this case, the only expression is `first + second`, the result of which becomes the returned value.
Here, `sumOf` is the name of the function, while `first` and `second` are the inputs to the function. If you are familiar with another programming language you may have noticed the absence of any sort of `return` statement. That's because in Gren everything is an expression. The body of a function is just a single expression too. In this case, the expression is `first + second`, the result of which becomes the returned value. If you want to write a more complex function in a step-by-step way, the [`let`](/book/syntax/lets/) keyword allows for this and is covered in a later section.

Functions can take an arbitrary number of arguments, but must return exactly one value.
Functions can take an arbitrary number of arguments, but return exactly one value.

Function arguments can be passed on multiple lines:

Expand All @@ -30,7 +41,7 @@ It looks kind of silly here, but it is helpful to know this when you’re readin

## Function Pipelines

You can chain multiple function calls with parenthesis:
When you need the result of one function as an input to another, you can use parenthesis to indicate this:

```elm
multiply first second =
Expand All @@ -39,8 +50,9 @@ multiply first second =
secondsInYear =
multiply 365 (multiply 24 (multiply 60 60))
```
Here the result of `multiply 60 60` becomes the second argument to `multiply 24` and the result of THAT becomes the second argument to `multiply 365`. This "inside-out" nesting is common in other programming languages and it works the same here, but Gren has a way of making this kind of chaining really nice to read.

But you can make this more readable with the `|>` operator:
We can make the above expression more readable with the `|>` operator:

```elm
secondsInYear =
Expand All @@ -53,6 +65,33 @@ secondsInYear =
`|>` passes the value on the left as the last argument to the function on the right.
For example `sumOf 1 2 |> multiply 3` is the same as `multiply 3 (sumOf 1 2)`.

## Partial Application

Functions in Gren take their arguments one at a time. When we do `multiply 60 24` we're actually doing this `((multiply 60) 24)`. First the argument `60` is applied, then the argument `24` is applied to the result of _that_. But what is the result of `multiply 60`? You might think it's an error, but in Gren it is not!

```elm
multiplyBySixty = multiply 60
```

`multiplyBySixty` is now a new function that takes one argument and multiplies it by 60. We can use it like any other function:

```elm
multiplyBySixty 24
-- returns 1440
```

This is called partial application and it's what makes the pipeline operator work. In the pipeline example above, `multiply 60` returns a new function waiting for one more argument, and `|>` provides that argument.

```elm
secondsInYear =
60
|> multiply 60 -- multiply 60 returns a function, 60 is passed to it
|> multiply 24 -- multiply 24 returns a function, result is passed to it
|> multiply 365
```

Functions that take one argument at a time like this are known as curried functions. In some languages you have to do this yourself, in Gren it's automatic.

## Anonymous Functions

You can create functions without giving them a name:
Expand Down
47 changes: 47 additions & 0 deletions src/content/docs/syntax/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,53 @@ For functions it get's a little bit more complicated. `->` can be read as `to`.

When reading the type signature of a function, the last `->` points to the return value of the function, while the types before represent the inputs.

While Gren is good at inferring the types for your functions, it's often helpful to put an explicit type declaration on your function. This can serve as documentation as well as helping the compiler give you better error messages.

## Function Types and Partial Application

You may notice that the `->` symbol between function arguments is the same as the symbol before the return type. This is not a coincidence. As covered in the [functions](/book/syntax/functions/#partial-application) section, functions in Gren take their arguments one at a time, which is called curried form.

Type signatures reveal what's really going on. A function like `multiply : Int -> Int -> Int` is actually `multiply : Int -> (Int -> Int)` - a function that takes an `Int` and returns a function of type `Int -> Int`. The first argument has been applied, but not the second so you have a partially applied function.

```elm
multiply : Int -> (Int -> Int)
multiply 60

result : Int -> Int
24

result : Int
1440
```

One place where this might cause confusion is when you accidentally forget an argument. Consider a function like this:

```elm
validateUser : User -> Email -> DateTime -> Flags -> Status
```

With that many arguments, you might easily forget one:

```elm
userStatus = validateUser user currentEmail now
```

`userStatus` is not a value of type `Status` - it is a function of type `Flags -> Status`. It can be confusing when you go to compare `userStatus` with a `Status` like this `if userStatus == LoggedIn then` and get an error:

```
TYPE MISMATCH - I need both sides of (==) to be the same type:

1| if userStatus == LoggedIn then
#^^^^^^^^^^^^^^^^^^^^#
The left side of (==) is:
#Flags -> Status#

But the right side is:
Status
```

Fortunately Gren's error messages are descriptive so you can work out what has gone wrong.

## Type Aliases

```elm
Expand Down