Source code for pymonad.writer

# --------------------------------------------------------
# (c) Copyright 2014, 2020 by Jason DeLaat.
# Licensed under BSD 3-clause licence.
# --------------------------------------------------------
""" Implements the Writer monad.

The Writer monad is typically used to append information to a log. The
log type is often just strings but can be any type that behaves as a
monoid with a defined + (__add__) operator.

Example:
    >>> @curry(2)
    >>> def add(x, y):
    >>>     return Writer(x + y, f"Called function 'add' with arguments {x} and {y}. Result: {x + y}")

    >>> @curry(2)
    >>> def mul(x, y):
    >>>     return Writer(x * y, f"Called function 'mul' with arguments {x} and {y}. Result: {x * y}")

    >>> logged_arithmetic = (Writer
    >>>                      .insert(0)
    >>>                      .then(add(1))
    >>>                      .then(mul(2)))

    >>> # logged_arithmetic = (2, "Called function 'add' with arguments 1 and 0. Result: 1
    >>> #                     Called function 'mul' with arguments 2 and 1. Result: 2")
"""
from typing import Callable, Generic, List, TypeVar

import pymonad.monad
import pymonad.monoid

M = TypeVar(
    "M", int, str, List, pymonad.monoid.Monoid, pymonad.monoid.ZERO
)  # pylint: disable=invalid-name
S = TypeVar("S")  # pylint: disable=invalid-name
T = TypeVar("T")  # pylint: disable=invalid-name


[docs]class Writer(pymonad.monad.Monad, Generic[M, T]): """ The Writer monad class. """
[docs] @classmethod def insert(cls, value: T) -> "Writer[M, T]": """ See Monad.insert. """ return Writer(value, pymonad.monoid.ZERO)
[docs] def bind( self: "Writer[M, S]", kleisli_function: Callable[[S], "Writer[M, T]"] ) -> "Writer[M, T]": """ See Monad.bind. """ result = kleisli_function(self.value) return Writer(result.value, self.monoid + result.monoid)
[docs] def map(self: "Writer[M, S]", function: Callable[[S], T]) -> "Writer[M, T]": """ See Monad.map. """ return Writer(function(self.value), self.monoid)
def __eq__(self, other): return self.value == other.value and self.monoid == other.monoid def __repr__(self): return f"({self.value}, {self.monoid})"