# Path: oslash/writer.py
# class Writer(Generic[TSource, TLog]):
# class MonadWriter(Writer[Any, TLog]):
#     def __init__(self, value: TSource, log: TLog) -> None:
#     def map(self, func: Callable[[Tuple[TSource, TLog]], Tuple[TResult, TLog]]) -> 'Writer[TResult, TLog]':
#     def bind(self, func: Callable[[TSource], 'Writer[TResult, TLog]']) -> 'Writer[TResult, TLog]':
#     def unit(cls, value: TSource) -> 'Writer[TSource, TLog]':
#     def run(self) -> Tuple[TSource, TLog]:
#     def apply_log(a: tuple, func: Callable[[Any], Tuple[TSource, TLog]]) -> Tuple[TSource, TLog]:
#     def create(cls, class_name: str, monoid_type=Union[Monoid, str]):
#         def unit(cls, value):
#     def __eq__(self, other) -> bool:
#     def __str__(self) -> str:
#     def __repr__(self) -> str:
#     def tell(cls, log: TLog) -> 'MonadWriter':
# 
# Path: oslash/monadic.py
# def compose(f: Callable[[Any], Monad], g: Callable[[Any], Monad]) -> Callable[[Any], Monad]:
#     r"""Monadic compose function.
# 
#     Right-to-left Kleisli composition of two monadic functions.
# 
#     (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
#     f <=< g = \x -> g x >>= f
#     """
#     return lambda x: g(x).bind(f)


import unittest
from oslash import StringWriter, MonadWriter
from oslash.monadic import compose



class TestMonadMonadic(unittest.TestCase):

    def test_monad_monadic_compose(self):
        unit, tell = StringWriter.unit, MonadWriter.tell

        def half(x):
            return tell("I just halved %s!" % x).bind(lambda _: unit(x//2))

        quarter = compose(half, half)
        value, log = quarter(8).run()


# Path: oslash/writer.py
# class Writer(Generic[TSource, TLog]):
# class MonadWriter(Writer[Any, TLog]):
#     def __init__(self, value: TSource, log: TLog) -> None:
#     def map(self, func: Callable[[Tuple[TSource, TLog]], Tuple[TResult, TLog]]) -> 'Writer[TResult, TLog]':
#     def bind(self, func: Callable[[TSource], 'Writer[TResult, TLog]']) -> 'Writer[TResult, TLog]':
#     def unit(cls, value: TSource) -> 'Writer[TSource, TLog]':
#     def run(self) -> Tuple[TSource, TLog]:
#     def apply_log(a: tuple, func: Callable[[Any], Tuple[TSource, TLog]]) -> Tuple[TSource, TLog]:
#     def create(cls, class_name: str, monoid_type=Union[Monoid, str]):
#         def unit(cls, value):
#     def __eq__(self, other) -> bool:
#     def __str__(self) -> str:
#     def __repr__(self) -> str:
#     def tell(cls, log: TLog) -> 'MonadWriter':
# 
# Path: oslash/monadic.py
# def compose(f: Callable[[Any], Monad], g: Callable[[Any], Monad]) -> Callable[[Any], Monad]:
#     r"""Monadic compose function.
# 
#     Right-to-left Kleisli composition of two monadic functions.
# 
#     (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
#     f <=< g = \x -> g x >>= f
#     """
#     return lambda x: g(x).bind(f)


# Path: tests/test_monad.py
import unittest
from oslash import StringWriter, MonadWriter
from oslash.monadic import compose




class TestMonadMonadic(unittest.TestCase):

    def test_monad_monadic_compose(self):
        unit, tell = StringWriter.unit, MonadWriter.tell

        def half(x):
            return tell("I just halved %s!" % x).bind(lambda _: unit(x//2))

        quarter = compose(half, half)
        value, log = quarter(8).run()


        self.assertEqual(2, value)