Functor Design Pattern in Python

Lesson Introduction

Welcome! Today, we'll learn about the Functor Design Pattern in Python. You might wonder, what is a Functor, and why should you care? Functors come from functional programming, making your code more modular and easier to understand.

Our goal is to understand functors and use them in Python to manage and transform values neatly. By the end, you'll know how to create and use functors effectively.

What is a Functor?

A Functor is a design pattern for mapping or transforming data. Think of it as a container for a value that can apply a function to the value inside. Imagine you have a box with a toy inside, and you want to paint the toy. You don't need to open the box; you apply the paint directly to the toy inside. That's what a Functor does—it applies functions to values without opening the "box."

In simple terms, a Functor:

  1. Holds a value.
  2. Provides a map method to apply a function to the value inside.

Creating a Functor in Python

Let's create a basic Functor class in Python using type annotations.

from typing import Generic, TypeVar

# Define type variables
T = TypeVar('T')

# Functor class
class Functor(Generic[T]):
    def __init__(self, value: T):
        self.value = value

In this code:

  • We define type variable T to make Functor generic.
  • Our Functor class is generic and can hold any type.
  • The __init__ method initializes the functor with a value of type T.

The `map` Method in Python Functors

Let's add the map method to our Functor. This method takes a function as an argument and returns a new functor with the transformed value. As the function is not guaranteed to return a value of the same type T, we will define another type, U, and use it to define the return type.

from typing import Generic, TypeVar, Callable

# Define type variables
T = TypeVar('T')
U = TypeVar('U')

class Functor(Generic[T]):
    def __init__(self, value: T):
        self.value = value
    
    def map(self, f: Callable[[T], U]) -> "Functor[U]":
        return Functor(f(self.value))

The map method:

  • Takes a function f that transforms a value of type T into U. T and U can be the same, but is not guaranteed.
  • Applies the function to the current value.
  • Returns a new functor with the transformed value.

Note that we use double quotes to annotate the map method's return type. When defining a method within a class that returns an instance of that class, Python's type hints need to refer to the class before it's fully defined. By putting the type inside quotes, we're telling Python to interpret it as a forward reference. This allows us to specify that the return type will be Functor[U] even though Functor isn't fully defined when this type hint is written.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal