# 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':


import unittest
from oslash import Writer, StringWriter



class TestWriterMonad(unittest.TestCase):
    def test_writer_return(self):
        w = StringWriter.unit(42)
        self.assertEqual(w.run(), (42, ""))

    def test_writer_unitint_log(self):
        IntWriter = Writer.create("IntWriter", int)
        w = IntWriter.unit(42)
        self.assertEqual(w.run(), (42, 0))

    def test_writer_monad_bind(self):
        entry = "Multiplied by 10"
        m = StringWriter.unit(42).bind(lambda x: StringWriter(x*10, entry))
        self.assertEqual(m, StringWriter(420, entry))

    def test_writer_monad_law_left_identity(self):
        # return x >>= f == f x
        entry = "Added 100000 to %s"
        a = StringWriter.unit(42).bind(lambda x: StringWriter(x+100000, entry % x))
        b = (lambda x: StringWriter(x+100000, entry % x))(42)
        self.assertEqual(a, b)

    def test_writer_monad_law_right_identity(self):
        # m >>= return is no different than just m.
        a = StringWriter.unit(42).bind(StringWriter.unit)

# 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: tests/test_writer.py
import unittest
from oslash import Writer, StringWriter




class TestWriterMonad(unittest.TestCase):
    def test_writer_return(self):
        w = StringWriter.unit(42)
        self.assertEqual(w.run(), (42, ""))

    def test_writer_unitint_log(self):
        IntWriter = Writer.create("IntWriter", int)
        w = IntWriter.unit(42)
        self.assertEqual(w.run(), (42, 0))

    def test_writer_monad_bind(self):
        entry = "Multiplied by 10"
        m = StringWriter.unit(42).bind(lambda x: StringWriter(x*10, entry))
        self.assertEqual(m, StringWriter(420, entry))

    def test_writer_monad_law_left_identity(self):
        # return x >>= f == f x
        entry = "Added 100000 to %s"
        a = StringWriter.unit(42).bind(lambda x: StringWriter(x+100000, entry % x))
        b = (lambda x: StringWriter(x+100000, entry % x))(42)
        self.assertEqual(a, b)

    def test_writer_monad_law_right_identity(self):
        # m >>= return is no different than just m.
        a = StringWriter.unit(42).bind(StringWriter.unit)

        self.assertEqual(a, StringWriter.unit(42))