mirror of
https://github.com/correl/typesafe-monads.git
synced 2025-03-29 01:09:10 -09:00
set with test
This commit is contained in:
parent
43d46bce44
commit
c61baf51c1
3 changed files with 102 additions and 2 deletions
|
@ -2,6 +2,7 @@ from .functor import Functor
|
|||
from .applicative import Applicative
|
||||
from .monad import Monad
|
||||
from .list import List
|
||||
from .set import Set
|
||||
from .maybe import Maybe, Just, Nothing
|
||||
from .result import Result, Ok, Err
|
||||
from .future import Future
|
||||
|
|
99
monads/set.py
Normal file
99
monads/set.py
Normal file
|
@ -0,0 +1,99 @@
|
|||
from __future__ import annotations
|
||||
from functools import reduce
|
||||
from itertools import chain
|
||||
from monads import functor, List
|
||||
from typing import (
|
||||
Callable,
|
||||
Iterable,
|
||||
Iterator,
|
||||
Set as _Set,
|
||||
List as _List,
|
||||
Optional,
|
||||
TypeVar,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
from .monad import Monad
|
||||
from .monoid import Monoidal
|
||||
from .currying import CurriedBinary, uncurry
|
||||
|
||||
T = TypeVar("T")
|
||||
S = TypeVar("S")
|
||||
|
||||
|
||||
class Set(Monad[T], Monoidal[set]):
|
||||
@classmethod
|
||||
def pure(cls, value: T) -> Set[T]:
|
||||
t = set()
|
||||
t.add(value)
|
||||
return Set(t)
|
||||
|
||||
def bind(self, function: Callable[[T], Set[S]]) -> Set[S]:
|
||||
return reduce(Set.mappend, map(function, self.value), Set.mzero())
|
||||
|
||||
def map(self, function: Callable[[T], S]) -> Set[S]:
|
||||
return Set(set(map(function, self.value)))
|
||||
|
||||
def apply(self, functor: Set[Callable[[T], S]]) -> Set[S]:
|
||||
|
||||
return Set(
|
||||
set(chain.from_iterable([map(f, self.value) for f in functor.value]))
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def mzero(cls) -> Set[T]:
|
||||
return cls(set())
|
||||
|
||||
@classmethod
|
||||
def sequence(cls, xs: Iterable[Set[T]]) -> Set[_List[T]]:
|
||||
"""Evaluate monadic actions in sequence, collecting results."""
|
||||
|
||||
def mcons(acc: Set[_Set[T]], x: Set[T]) -> Set[_Set[T]]:
|
||||
return acc.bind(lambda acc_: x.map(lambda x_: acc_.union(set([x_]))))
|
||||
|
||||
empty: Set[_Set[T]] = Set.pure(set())
|
||||
return Set(set(reduce(mcons, xs, empty))) # type: ignore
|
||||
|
||||
def flatten(self) -> Set[T]:
|
||||
def flat(acc: Set[T], element: T) -> Set[T]:
|
||||
if element and isinstance(element, Iterable):
|
||||
for k in element:
|
||||
acc = acc.mappend(Set(set([k])))
|
||||
elif element:
|
||||
acc = acc.mappend(Set(set([element])))
|
||||
return acc
|
||||
|
||||
return Set(reduce(flat, self, Set.mzero())) # type: ignore
|
||||
|
||||
def sort(self, key: Optional[str] = None, reverse: bool = False) -> Set[T]:
|
||||
lst_copy = self.value.copy()
|
||||
lst_copy.sort(key=key, reverse=reverse) # type: ignore
|
||||
return Set(lst_copy)
|
||||
|
||||
def fold(
|
||||
self, func: Union[Callable[[S, T], S], CurriedBinary[S, T, S]], base_val: S
|
||||
) -> S:
|
||||
if isinstance(func, CurriedBinary):
|
||||
functor = uncurry(cast(CurriedBinary, func))
|
||||
else:
|
||||
functor = func
|
||||
return reduce(functor, self.value, base_val) # type: ignore
|
||||
|
||||
__and__ = lambda other, self: Set.apply(self, other) # type: ignore
|
||||
|
||||
def mappend(self, other: Set[T]) -> Set[T]:
|
||||
return Set(self.value.union(other.value))
|
||||
|
||||
__add__ = mappend
|
||||
__mul__ = __rmul__ = map
|
||||
__rshift__ = bind
|
||||
|
||||
def __sizeof__(self) -> int:
|
||||
return self.value.__sizeof__()
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(set(self.value))
|
||||
|
||||
def __iter__(self) -> Iterator[T]:
|
||||
return iter(self.value)
|
|
@ -1,8 +1,8 @@
|
|||
import pytest # type: ignore
|
||||
from typing import Type
|
||||
from monads import Maybe, List, Result
|
||||
from monads import Maybe, List, Result, Set
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", params=[Maybe, List, Result])
|
||||
@pytest.fixture(scope="module", params=[Maybe, List, Result, Set])
|
||||
def monad(request) -> Type:
|
||||
return request.param
|
||||
|
|
Loading…
Add table
Reference in a new issue