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.2.tar.gz (9.2 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.2-py3-none-any.whl (7.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for undercat-0.1.2.tar.gz
Algorithm Hash digest
SHA256 352df9b4935ef0e761a74773800f9638aea012b4822d21cc77521d5a33a40cae
MD5 36dd5da8b515d254e64a926920a0a84d
BLAKE2b-256 feca4ff2dc04a2bda6d65f51b4f0cfe15785f2f6a1838c0fb56e1208673d2d12

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for undercat-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 abf3a0935ae1fe09ab561fd99745fc890e79dc8ce0c84b0cdd3a20036dcdcd3d
MD5 353dd45fab9a869770a210bc223786a8
BLAKE2b-256 73257348fab9be964fd1cbd0f5af140148abeb1e30d4597caa125d00964fe9a7

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