typesafe-monads/monads/monoid.py

74 lines
1.9 KiB
Python
Raw Permalink Normal View History

2018-10-12 00:44:57 +00:00
from __future__ import annotations
from functools import reduce
2018-10-13 06:27:39 +00:00
from numbers import Complex
from decimal import Decimal
from typing import Any, Callable, Generic, Iterator, Type, TypeVar, Union
2018-10-12 00:44:57 +00:00
T = TypeVar("T")
class Monoid(Generic[T]):
def __init__(self, value: T) -> None:
self.value = value
# FIXME: Other type set to Any, as the proper value (Monoid[T]) is
# reported as incompatible with subclass implementations due to a
# flaw in mypy: https://github.com/python/mypy/issues/1317
def mappend(self, other: Any) -> Monoid[T]: # pragma: no cover
2018-10-12 00:44:57 +00:00
raise NotImplementedError
@classmethod
def mzero(cls) -> Monoid[T]: # pragma: no cover
2018-10-12 00:44:57 +00:00
raise NotImplementedError
@classmethod
def mconcat(cls, xs: Iterator[Monoid[T]]) -> Monoid[T]:
return reduce(cls.mappend, xs, cls.mzero())
def __eq__(self, other: object) -> bool:
return (
isinstance(other, Monoid)
and type(self) == type(other)
and self.value == other.value
)
__add__ = mappend
2018-10-13 06:27:39 +00:00
class Monoidal(Monoid[T]):
def __repr__(self): # pragma: no cover
return repr(self.value)
class String(Monoidal[str]):
@classmethod
def mzero(cls) -> Monoidal:
return cls(str())
def mappend(self, other: String) -> String:
return String(self.value + other.value)
__add__ = mappend
class Addition(Monoidal[Union[int, float]]):
@classmethod
def mzero(cls) -> Addition:
return cls(0)
def mappend(self, other: Addition) -> Addition:
return Addition(self.value + other.value)
__add__ = mappend
class Multiplication(Monoidal[Union[int, float]]):
@classmethod
def mzero(cls) -> Multiplication:
return cls(1)
def mappend(self, other: Multiplication) -> Multiplication:
return Multiplication(self.value * other.value)
__add__ = mappend