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.1.tar.gz (9.1 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.1-py3-none-any.whl (7.3 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for undercat-0.1.1.tar.gz
Algorithm Hash digest
SHA256 dc0e4654672f50319632da5146d7e03eb8bd572fce40012529b88450aa92f060
MD5 820bf9375f45bfcc8a1f78853a815f7a
BLAKE2b-256 6f9f5615e355515131ca7e0aa0ad9cd31be2dcd3dba91c0704ee76a7eeca7486

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for undercat-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 93f7b8adc68e78d6960ef261ca861e81cfa4efb50127ed798b4302e14753c465
MD5 136c8ddce3a7b58f35802f54feabe97d
BLAKE2b-256 118f2dcb1ebf2018dc06ddd1eb54b0290308209e9d50633ab568b5584d625d83

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