We are not going to transform code into curry but rather try to curry some code. As a former C# developer, when I started Haskell, I felt like functions were very differents from what I was used to see in object oriented languages. **I just forgot maths**:

$$

f : \mathbb{Z} \to \mathbb{Z} \to \mathbb{Z} \to \mathbb{Z}

\\

f(x, y, z) = x + y + z

$$

```
public static int f(int x, int y, int z) => x + y + z;
```

```
f :: Int -> Int -> Int -> Int
f x y z = x + y + z
```

Everyone was used to see the mathematical definition at school. Why do we have such a verbose and ugly notation is OOP? I don't have the answer but I believe that it is far **easier to read the Haskell definition**.

In opposition, the C# side is **mixing** both the **function signature** and its **implementation**, this is a reason why it is harder to read (note that we are using the version 7 of C#, it would be worse otherwise).

Now let's think a little bit about $f$. The function is telling us:

Give me $x$, $y$, and $z$. I will give you $x + y + z$.

We can rephrase this sentence:

Give me $x$ and then $y$ and finally $z$. I will give you $x + y + z$

This is very important. Providing the three variables at the **same time is not mandatory**. What I mean is that we can **first fix** $x$, then fix $y$ and fix $z$ **later**. Let's welcome currying:

$$

f : x \mapsto y \mapsto z \mapsto x + y + z

$$

This mathematical definition is pretty much straight forward. The function $f$ is a **map of map of map**, it's possible to fix the variables **step by step by step**:

$$

\begin{eqnarray*}

g &=& f(1)

\\

g &:& y \mapsto z \mapsto 1 + y + z

\\

\\

h &=& g(2)

\\

h &:& z \mapsto 1 + 2 + z

\\

\\

i &=& h(3)

\\

&=& 6

\\

&=& h(3)

\\

&=& g(2)(3)

\\

&=& f(1)(2)(3)

\end{eqnarray*}

$$

What we want to understand here is that we can treat **every function** as a function of a **single argument**:

$$f(1, 2, 3) = f(1)(2)(3)$$

Instead of providing every parameters at once, we **fix them one at a time**. This give us more flexibility. Now remove the useless commas and parenthesis:

$$f\enspace1\enspace2\enspace3 = f\enspace1\enspace2\enspace3$$

Wow, go back to our Haskell definition:

```
f :: Int -> Int -> Int -> Int
f x y z = x + y + z
```

You can **partially apply functions** in Haskell, every function is a function of a single argument. What you don't see here is the implicit right associative arrow `Int -> (Int -> (Int -> Int))`

. We can read it as **a function of function of function**.

Applying a parameter to a function is just a matter of space `f a`

. With the application being left associative `f a b = (f a) b`

:

```
f :: Int -> Int -> Int -> Int
f x y z = x + y + z
k :: Int -> Int
k = f 1 2
```

Having this kind of behaviour in C# is pretty hard as we have to write a lot of boilerplate code to reach the same level of abstraction:

```
public static int f(int x, int y, int z)
=> x + y + z;
public static Func<int, Func<int, Func<int, int>>> curriedf =
x
=> y
=> z
=> x + y + z;
```

Unfortunately, the code is ugly and unreadable, notice how it is hard to understand the nested **Func**. Perhaps you ask yourself whether this concept is useful or not. Imagine that you want to filter a list of persons by their age:

```
public static bool OlderThan30(Person person) => person.Age > 30;
// call site
var persons = new List<Person>(...);
var result = persons.Where(OlderThan30);
```

```
olderThan30 :: Person -> Bool
olderThan30 person = age person > 30
-- call site
persons = [...]
result = filter olderThan30 persons
```

Now, you realize that you also want to filter people older than 50. You try to abstract the function by accepting the lower bound as a parameter, but **you are stuck** to write:

```
public static bool OlderThan(int lowerBound, Person person)
=> person.Age > lowerBound;
// call site
var persons = new List<Person>(...);
/* Impossible to write this even if it mathematically equivalent
var result = persons.Where(OlderThan(50));
*/
Func<Person, bool> olderThan50 = person => OlderThan(50, person);
var result = persons.Where(olderThan50);
```

```
olderThan :: Int -> Person -> Bool
olderThan lowerBound person = age person > lowerBound
-- call site
persons = [...]
result = filter (olderThan 50) persons
```

Regrettably, the `Where`

function is accepting a function of a single argument, but we are not able to partially apply `OlderThan`

in C#. We are forced to have an intermediate function (`olderThan50`

) to **give all the parameters at once**...

Moreover, the compiler is not able to infer `Func<Person, bool>`

as we can't replace it by `var`

.

Thanks for reading.

https://en.wikipedia.org/wiki/Currying

https://wiki.haskell.org/Currying