### Partial functions, currying and composition

I've been working through

First is partial function application. In Scala my solution to this exercise looks as follows.

Next we have currying, which I'd heard of previously by reading a little about Haskell, but never fully understood. In Scala I've added the following method to the singleton above.

\begin{align}(A^{N}\rightarrow B)\underset{\text{Uncurry}}{\overset{\text{Curry}}{\require{extpfeil} \Newextarrow{\xrightharpoonup}{1,5}{0x21CC}\xrightharpoonup{}}}(A^{1}\longrightarrow\cdots\longrightarrow A^{N}\longrightarrow B).\end{align} In words,

In Scala I've implemented this method as follows (it's a

*Functional Programming in Scala*by Chiusano and Bjarnason lately, and it's been a really awesome book. This morning I worked on a few exercises on partial function application, currying and composition that I think demonstrate how powerful Scala can be. I just wanted to paste my solutions here and their translations to Python (3.6), because it's really cool and I'd love feedback on them.#### Partial Function Application

First is partial function application. In Scala my solution to this exercise looks as follows.

object HOF_Testing { def partial[A, B, C](a: A, f: (A, B) => C): B => C = (b: B) => f(a, b) def main(args: Array[String]): Unit = { // Test this partial function method on an anonymous function val x = 5 val y = 6 println("** Partial function application: " + partial[Int, Int, Int](x, (u, v) => u + v)(y)) } } // ** Partial function application: 11In Python we can achieve the same result by just importing

`functools.partial`

, or mimicking the Scala code above in a singleton object. Also, I'd like to point out that all methods are static per Scala's documentation on singleton objects. (In my experience, classes full of nothing but static methods in Python is generally discouraged.)#! /usr/bin/env python3.6 # -*- coding: utf-8 -*- """ Get similar functionality in Python with HOF as I did in Scala """ from types import FunctionType as Function from functools import partial from typing import Any, Optional class Singleton(type): """ A metaclass to make a singleton object (again, mimicking Scala's `object`) """ _instance: Optional[type] = None def __call__(cls, *args, **kwargs) -> type: # If an instance of this class doesn't already exist, create it; otherwise, # return that instance if not cls._instance: cls._instance = cls.__call__(*args, **kwargs) else: return cls._instance class HOF_Testing(metaclass=Singleton): """ A bunch of HOF methods to compare to my implementations in Scala """ @staticmethod def partial(a: Any, f: Function) -> Function: return lambda b: f(a, b) if __name__ == '__main__': x: int = 5 y: int = 6 # Some function that works on integers def foo(a: int, b: int) -> int: return a + b print(f'** functools.partial application: {partial(foo, x)(y)}') print(f'** Partial function application : {HOF_Testing.partial(x, foo)(y)}') # ** functools.partial application: 11 # ** Partial function application : 11

#### Currying

Next we have currying, which I'd heard of previously by reading a little about Haskell, but never fully understood. In Scala I've added the following method to the singleton above.

... def curry[A, B, C](f: (A, B) => C): A => (B => C) = (a: A) => partial[A, B, C](a, (a: A, b: B) => f(a, b)) ...And in the

`main`

method we can test this as follows.
... println("** Curried anonymous function : " + curry[Int, Int, Int]((u, v) => u + v)(x)(y)) // ** Curried anonymous function : 11 ...In Python we can achieve this same kind of result with nested anonymous lambda functions in the singleton class.

... @staticmethod def curry(f: Function) -> Function: return lambda a: lambda b: f(a, b) ...As before, I can't think of any simple way to use Python's annotations to be as descriptive as Scala's typing system. Testing this method, we have the following output.

... print(f'** Currying : {HOF_Testing.curry(foo)(x)(y)}') # ** Currying : 11It's still just as straightforward, if not even more simple, but I can't say it's as pleasant to read. One might deduce that this can be extended to a variable number of arguments as well, though I'm not at all sure yet how to write such a method in Scala. In general I believe we have

\begin{align}(A^{N}\rightarrow B)\underset{\text{Uncurry}}{\overset{\text{Curry}}{\require{extpfeil} \Newextarrow{\xrightharpoonup}{1,5}{0x21CC}\xrightharpoonup{}}}(A^{1}\longrightarrow\cdots\longrightarrow A^{N}\longrightarrow B).\end{align} In words,

`curry`

converts a function of multiple arguments into a chain of single-argument functions. And `uncurry`

takes a chain of functions and morphs it into a function of several parameters.#### Uncurrying

*lot*simpler than you'd think when first approaching this problem)! At first I was trying to implement it using`partial`

in the opposite way of `curry`

, since they are, in a sense, inverses (perhaps from the perspective of category theory `curry`

would be deemed an isomorphism ?).... def uncurry[A, B, C](f: A => (B => C)): (A, B) => C = (a: A, b: B) => f(a)(b) ...Now in Python, with the help of a lambda, this looks virtually identical.

... @staticmethod def uncurry(f: Function) -> Function: return lambda a, b: f(a)(b) ...I also thought the following test with uncurrying was rather interesting because it resembles reversing a decorator pattern to some extent.

... def example1(a: int) -> Function: def _inner_example1(b: int) -> int: return a + b return _inner_example1 ... print(f'** Uncurrying : {HOF_Testing.uncurry(example1)(x, y)}') # ** Uncurrying : 11

#### Uncurrying a curried function and currying an uncurried function

In Scala this kind of functionality looks as follows.

In Scala I've written this method as follows.

... println("** Uncurrying a curry : " + uncurry[Int, Int, Int](curry((x, y) => x + y))(num1, num2)) println("** Currying an uncurry: " + curry[Int, Int, Int](uncurry(x => y => x + y))(num1)(num2)) // ** Uncurrying a curry : 11 // ** Currying an uncurry: 11It's actually really interesting seeing them side-by-side and observing the difference in the way we call the function to see its value. Python isn't much different from that above, either.

... print(f'** Uncurrying a curry : {HOF_Testing.uncurry(HOF_Testing.curry(foo))(x , y)}') print(f'** Currying an uncurry : {HOF_Testing.curry(HOF_Testing.uncurry(example1))(x)(y)}') # ** Uncurrying a curry : 11 # ** Currying an uncurry : 11

#### Function Composition

In Scala I've written this method as follows.

... def compose[A, B, C](f: A => B, g: B => C): A => C = (a: A) => g(f(a)) ...It's another beautiful one-liner. In Python, again, it's less descriptive, but very similar.

... @staticmethod def compose(f: Function, g: Function) -> Function: return lambda a: f(g(a)) ... def one(a: int) -> int: return 2 * a def two(b: int) -> int: return b + 1 ... print(f'** Compose functions : {HOF_Testing.compose(one, two)(y)}') # ** Compose functions : 14Referencing again Peter Thatcher's monads article, it's possible to compose functions using decorators as well.

from functools import wraps ... @staticmethod def compose_using_decorators(f: Function, g: Function) -> Function: # A function that makes a function a decorator def make_decorate(func) -> Function: # Avoid using exceptions if we can, that's what monads are for! if 'return' in func.__annotations__.keys(): ret_type = func.__annotations__['return'] else: ret_type = Any @wraps(func) def decorator(undecorated) -> Function: @wraps(undecorated) def decorated(*args, **kwargs) -> ret_type: return func(undecorated(*args, **kwargs)) return decorated return decorator # decorate g with f return make_decorate(f)(g) ... print(f'** Compose with decorators : {HOF_Testing.compose_using_decorators(one, two)(y)}') # ** Compose with decorators : 14Although I doubt such a complicated solution is ever better than a simple \(\lambda\). Also, it's interesting how this application resembles

`curry`

.
## Comments

## Post a Comment