Skip to main content

Library implementing the covariant Hom (AKA "Reader") functor.

Project description

Undercat

PyPI - Version GitHub Actions Workflow Status Coverage Status License: MIT pre-commit

Undercat logo (a striped cat walking on the ceiling)

Undercat is a small Python library implementing a functional programming construct called the Reader functor. This pattern is particularly useful for dependency injection, composing functions, and operating on immutable, context-aware computations.

The Reader functor is ideal when you need to:

  • Pass a shared dependency or context (e.g., configuration, environment) through multiple computations without explicitly threading it through function calls.
  • Create pipelines of computation where each step depends on a shared state.
  • Enhance code readability by abstracting common operations such as accessing attributes or combining results.

Features

  • Function composition: Compose computations using a clean, declarative style.
  • Attribute and item access: Retrieve nested attributes or indexed elements with ease.
  • Operator overloading: Perform arithmetic, logical, and comparison operations directly on Reader objects.

Installation

pip install undercat

or (using uv)

uv pip install undercat

Quickstart

1. Basic Usage

Define a Reader that retrieves data from a context and operates on it:

import undercat as uc

class Context:
    """A context with a dict attribute."""
    def __init__(self, value):
        self.data = {'key': value}

# Define a Reader to get a nested value from a context.
get_value = uc.attrgetter('data').getitem('key')

context = Context(42)

# Execute the Reader with a context.
get_value(context)  # output: 42

2. Function Composition

Readers can be composed using .map to transform outputs:

get_value_and_increment = get_value.map(lambda x: x + 1)

# Execute the modified Reader.
get_value_and_increment(context)  # output: 43

3. Combining Readers

Combine multiple Readers into one using operators:

# Define a Reader that squares its input.
square = uc.Reader(lambda x: x * x)

# Define a Reader that leaves its input alone.
identity = uc.Reader(lambda x: x)

# Combine Readers arithmetically.
combined = square + identity

# Execute the Reader.
# Its constituent Readers act independently on the same input; the results are then added.
combined(3)  # output: 12 (3 * 3 + 3)
combined(5)  # output: 30 (5 * 5 + 5)

# Combine Readers to make a new Reader that produces a tuple.
combined = uc.make_tuple(square, identity)

combined(3)  # output: (9, 3)

# Create a Reader that produces a constant value for any input.
const10 = uc.const(10)

# Create a Reader that multiplies the output of its constituent Readers.
combined = uc.prod([const10, identity, square])

combined(3)  # Output: 270 (10 * 3 * 9)

API Overview

Core Methods

  • Reader(func): Wrap a function into a Reader.
  • uc.const(val): Create a Reader that always returns a constant value.
  • uc.attrgetter(attr, [default]): Access an attribute (or nested attributes) from a context.
  • uc.make_tuple(*readers): Combine multiple Readers into one that returns a tuple.

Operators

Readers support most logical/arithmetic operations:

  • Arithmetic: +, -, *, **, /, //, %, @
  • Boolean/bitwise logic: and, or, &, |, ^, ~
  • Comparisons: <, <=, >=, >
    • For equality you cannot use == and !=; instead use reader.equals(other) and reader.not_equals(other).

You can also apply operations to sequences of Readers using uc.sum, uc.prod, uc.all, uc.any, uc.min, uc.max, and uc.reduce.

License

This library is open-source and licensed under the MIT License.

Contributions are welcome!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

undercat-0.1.0.tar.gz (9.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

undercat-0.1.0-py3-none-any.whl (7.1 kB view details)

Uploaded Python 3

File details

Details for the file undercat-0.1.0.tar.gz.

File metadata

  • Download URL: undercat-0.1.0.tar.gz
  • Upload date:
  • Size: 9.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for undercat-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dc9ddd5045603b53dd898e5ed627af58b08e150956481d3798f6a8f156045219
MD5 6e4f908f1c8febe94e8f531cdc5c922d
BLAKE2b-256 174510192a53b72e1a6cb471cae870c220ee44b3c4721c117f467ec65a17f6c3

See more details on using hashes here.

File details

Details for the file undercat-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: undercat-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 7.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for undercat-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e76a24ddf043d5492d4cf7f1f401b0ded914955372d1ae60ce011ec89cffdbc3
MD5 f7628b63ca3ea122d80d1a0b1a55ddfa
BLAKE2b-256 44540cb0137930154a32e9fdde4958700ff117a370ac18332036fcc50ec413d9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page