*This post was originally posted on www.dailydrip.com and it was written by Jan Klimo.*

A friend of mine recently raised a very interesting question.

If a function takes two arguments, why is its type annotation

f: a -> b-> c? Wouldn’t something likef: (a, b) -> cmake more sense?

A solid understanding of how Elm treats functions will make the answer clear and allow us to write better code.

### One argument at a time

Let’s take the following example:

```
greeting : String -> String -> String
gretting hello name = hello ++ ", " ++ name ++ "!"
```

On the surface, this looks like a function that takes two arguments and returns a result:

```
greeting "Hello" "DailyDrip" == "Hello, DailyDrip!"
```

However, functions in Elm always take *exactly* one argument and return a result (hence the function type annotation syntax).

Passing a single argument to our greeting function returns a new function that takes one argument and returns a string (commented-out output in the examples below comes from elm-repl):

```
helloGreeting = greeting "Hello"
-- <function> : String -> String
```

Passing an additional argument to this partially applied function will yield the expected result:

```
helloGreeting "DailyDrip"
-- "Hello, DailyDrip!" : String
```

This shows that the following notation is equivalent:

```
greeting "Hello" "DailyDrip" == ((greeting "Hello") "DailyDrip")
```

Parentheses are optional because function evaluation associates to the left by default. Let’s take a look at some examples where partial application is especially useful.

### Expressive function definitions

Let’s begin with a simple example of a function that doubles a number. Our first take could be:

```
double n = n * 2
-- <function> : number -> number
```

The beautiful thing about Elm is that even operators are functions:

```
(*)
-- <function> : number -> number -> number
```

We can use partial application to be more concise while achieving the same result:

```
double = (*) 2
-- <function> : number -> number
```

Because **(*)** takes two numbers as arguments, the compiler will infer that our double function takes one number as its sole argument.

While a function to double all elements of a list could be written as:

```
doubleList list = List.map double list
-- <function> : List number -> List number
```

by applying the same principle, we can do better:

```
doubleList = List.map double
-- <function> : List number -> List number
```

### Piping

Now that we know that operators are functions too, we can fully grasp how piping works:

```
(|>)
-- <function> : a -> (a -> b) -> b
```

It really is no magic: the second argument is a function, which makes it one of the most common use cases for partial application. A good example to demonstrate it is the following function that returns the sum of all deposits:

```
amountDeposited : List Transaction -> Float
amountDeposited list =
List.filter (\t -> t.type_ == Deposit) list
|> List.map .amount
|> List.sum
-- rather than the nested equivalent:
-- List.sum (List.map .amount (List.filter (\t -> t.type_ == Deposit) list))
```

There’s one important design feature of Elm that makes all of this possible: data structure is always the last argument. This makes writing better, cleaner, more expressive code using piping and partial application a breeze.

## Top comments (7)

It's by design, which this article covers very well.

Well,

`f: (a, b) -> c`

is a type annotation for a function that takesone argument, a`tuple of a, b`

.This type annotation makes no assumptions about the concrete types. As such it's hard to tell if it makes sense to require a and b together prior to being applied.

It might seem like a silly question, but thinking about it, functions in Java and C# do exactly this, require all arguments at once in order to be applied. So if that's your background I'd say it's not such a strange question.

...

For my own understanding I prefer working with a more concrete example:

`getDistance2d : Int -> Int -> Int -> Int -> Int`

This function calculates the distance between 2 coordinates.

You might argue it's easier to deal with:

`getDistance2d : (Int, Int) -> (Int, Int) -> Int`

The X and Y of a coordinate belong together. So I'd say it's reasonable to apply them in a unified form. You could be more explicit about your intent using a composite type:

`getDistance2d: Coordinate -> Coordinate -> Int`

And if you really don't want any curried instances:

`getDistance2d: (Coordinate, Coordinate) -> Int`

But I find it hard to see the benefit of that. The arguments don't belong together like the X and Y components of a Coordinate. So why give up on the luxury of being able to curry?

Disclaimer: I know C# and a bit of Haskell, I googled to check if my examples make sense to an Elm programmer, correct me if I'm wrong.Nice article!

Slight tangentIn ReasonML

`f: (a,b) -> c`

is equivalent to`f: a -> b -> c`

in that you can partially apply the first argument by calling`f(aValue)`

.ReasonML - Function - Currying

When a newcomer to FP learns currying/partial application this way, now there is going to be a stumbling block when transitioning to other functional languages. Because every other function language I'm aware of actually means tuple when the function signature says tuple.

To express the equivalent greeting as a curried function in JavaScript (ES6):

I much prefer the Elm syntax. Much cleaner; obviously influenced by OCaml.

Puts functional programming first, and syntactically path of least resistance.

One of my buddies pointed out that it would be cleaner using more ES6-isms:

Just to clean this up.

I'm relatively new in FP but suspect the test for goodness of currying is in the readability.

Your example of the sum of all deposits is a good one because it uses commonly known functions and feels like chaining. These are particularly easy to understand when the same type goes in as out.

Creating the double function is another good one as it simple and very clear what is going on.

I'm wondering though when things are more complex. For example when you see code that shows an unfamiliar more complex function using two arguments and then suddenly it's used with one because a curried function is being created. My early issues with Elm were not being able to clearly see where a function and its parameters ended vs a Tagged value. There may be other situations.