Currying: for multi argument functions & your taste buds

Posted by StuffonmyMind on January 15, 2022

When I learnt about there being a language concept called Currying Well I just had to go learn more about it. The Indian in me would not and could not look the other way.

Named after Haskell Curry which is not a big deal cause this man already got three programming languages named after him, Currying is essentially an operation that takes a function of two or more arguments and converts it into a pipeline of functions which take one argument each

result = f(a,b,c) = g(a)(b)(c)
// break it down
d = g(a)
e = d(b)
result = e(c)

There is also another construct called partial application which is like Currying but we pass in too few arguments, cause its sometimes more cleaner and gives you these reusable functions.

e = f(a,b)
// Now I can call `e` independently
result = e(c)
// Reuse with another argument `i`
result_i = e(i)

Well this is super ! I sure hope this works nicely in my favorite programming language Python

1
2
def f(a, b, c):
    return "did i even curry {a} {b} {c}"

Umm this is embarrassing, Seems like we cannot call f(a) without passing all the 3 arguments, but I do really wanna curry tho so as the most developers do let’s find a workaround that makes everything much worse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def g(a):
    def d(b):
        def e(c):
            return f"Welp We Curried g({a}) d({b}) e({c})"
        return e
    return d

result_1 = g(1)(2)(3)
# split
d = g(1)
e = d(2)
result_2 = e(3)
# same2same
result_1 == result_2

This is gonna looks so much funnier when we have a hundred curried functions and also another major issue here is that we cannot call g(1,2,3) since g is now a one argument function

Finna take a look at how this works on SML

1
2
3
4
5
6
fun f a b c = a ^ b ^ c;
f "do you" "know" "haskell bro?"
(* partial *)
val d = f "do you"
val e = d know"
e "haskell bro?"

Well! that was quite pleasant

This is because SML functions technically can take only one argument & all the other arguments we passed are just functions take the first conceptual argument and return another function that takes the second conceptual argument and so on, so its essentially pipelining of functions

f a b c d e is essentially ((((f a) b) c) d) e

Mafs

Guess who has crippling anxiety and wants to replicate this language construct in Python even though its absolutely unnecessary

Python being pretty cool actually has functools which is an internal module for higher-order functions, we can make use of this to implement currying & partial applications

First up we have partial which can be used to implement partial applications

1
2
3
4
from functools import partial
n_x = lambda a, b : a * b
ten_x = partial(n_x, 10)
ten_x(20) # 200

This is done in SML without any extra module & I also find it easier to reason about

1
2
3
fun n_x a b = a * b
val ten_x = n_x 10;
ten_x 20 (* 200 *)

We can extend this a bit to actually implement our own basic curry function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from functools import partial
n_x = lambda a, b : a * b

def curry(f):
    def g(*arg):
        try:
            return f(*arg) # WTF pass only one arg, need to curry bro
        except TypeError: # Missing arguments
            return curry(partial(f, *arg)) # OMG Recursion
    return g

curried_nx = curry(n_x)

curried_nx(10, 20) # 200
ten_x = curried_nx(10)
ten_x(20) # 200

This is not fully correct cause we are not covering all the cases including args, kwargs, builtin functions, and also error handling, A proper implementation for this is available on pytoolz

https://github.com/pytoolz/toolz/blob/294e981edad035a7ac6f0e2b48f1738368fa4b34/toolz/functoolz.py#L170

The lesson here is to not follow this lesson and best leave these constructs to func languages

PS:

I made this while working through Programming Languages It is a beautiful course where I got to explore some these really cool language constructs like tail recursion, pattern matching, higher order functions etc. These were not taught to me in college cause functional languages were not a part of my curriculum, I dunno who made that call but well the internet always provides.

I made notes on the course material & programming exercises, iss up on this github repo