High-Order Transformers

A common need you probably will have is to create transformers that receive other transformers as arguments. This is called high-order transformers. It is a powerful feature that allows you to create more complex transformers by combining simpler ones.

Creating the “reduce” Transformer

Let’s create a transformer that receives a list of integers and apply a “reducer” transformer to combine them sequentially. The types of this first example will be all static and the transformer will be called “reduce” (inspired by reduce).

from gloe import partial_transformer, transformer, Transformer

@partial_transformer
def reduce(
    data: list[int],
    reducer: Transformer[tuple[int, int], int],
    initial_value: int = 0
) -> int:
    result = initial_value
    for num in data:
        result = reducer((result, num))
    return result


@transformer
def sum_tuple2(data: tuple[int, int]) -> int:
    return data[0] + data[1]


sum_all = reduce(sum_tuple2)

print(sum_all([1, 2, 3, 4]))  # returns 10

Creating the “Reduce” Generic Transformer

Now, let’s create a more generic version of the “reduce” transformer. This time, we will use the Generic type from Python’s typing module to allow the reducer to receive any type of data.

from gloe import Transformer
from typing import Generic, TypeVar

T = TypeVar('T')
S = TypeVar('S')

class Reduce(Generic[T, S], Transformer[list[T], S]):
    def __init__(self, reducer: Transformer[tuple[S, T], S], initial_value: S):
        super().__init__()

        self.reducer = reducer
        self.initial_value = initial_value

    def transform(self, data: list[T]) -> S:
        result = self.initial_value
        for num in data:
            result = self.reducer((result, num))
        return result


flow = Reduce(sum_tuple2, initial_value=0.0)
print(sum_all([1, 2, 3, 4]))  # returns 10