# Path: oslash/state.py
# class State(Generic[TSource, TState]):
#     """The state monad.
# 
#     Wraps stateful computations. A stateful computation is a function
#     that takes a state and returns a result and new state:
# 
#         state -> (result, state')
#     """
# 
#     def __init__(self, fn: Callable[[TState], Tuple[TSource, TState]]) -> None:
#         """Initialize a new state.
# 
#         Keyword arguments:
#         fn -- State processor.
#         """
# 
#         self._fn = fn
# 
#     @classmethod
#     def unit(cls, value: TSource) -> "State[TSource, TState]":
#         r"""Create new State.
# 
#         The unit function creates a new State object wrapping a stateful
#         computation.
# 
#         State $ \s -> (x, s)
#         """
#         return cls(lambda state: (value, state))
# 
#     def map(self, mapper: Callable[[TSource], TResult]) -> "State[TResult, TState]":
#         def _(a: Any, state: Any) -> Tuple[Any, Any]:
#             return mapper(a), state
# 
#         return State(lambda state: _(*self.run(state)))
# 
#     def bind(self, fn: Callable[[TSource], "State[TState, TResult]"]) -> "State[TResult, TState]":
#         r"""m >>= k = State $ \s -> let (a, s') = runState m s
#         in runState (k a) s'
#         """
# 
#         def _(result: Any, state: Any) -> Tuple[Any, Any]:
#             return fn(result).run(state)
# 
#         return State(lambda state: _(*self.run(state)))
# 
#     @classmethod
#     def get(cls) -> "State[TState, TState]":
#         r"""get = state $ \s -> (s, s)"""
#         return State(lambda state: (state, state))
# 
#     @classmethod
#     def put(cls, new_state: TState) -> "State[Tuple, TState]":
#         r"""put newState = state $ \s -> ((), newState)"""
#         return State(lambda state: (Unit, new_state))
# 
#     def run(self, state: TState) -> Tuple[TSource, TState]:
#         """Return wrapped state computation.
# 
#         This is the inverse of unit and returns the wrapped function.
#         """
#         return self._fn(state)
# 
#     def __call__(self, state: Any) -> Tuple:
#         return self.run(state)
# 
# Path: oslash/util/fn.py
# A = TypeVar("A")
# B = TypeVar("B")
# C = TypeVar("C")
# D = TypeVar("D")
# E = TypeVar("E")
# F = TypeVar("F")
# G = TypeVar("G")
# def compose() -> Callable[[A], A]:  # pylint: disable=function-redefined
# def compose(op1: Callable[[A], B]) -> Callable[[A], B]:  # pylint: disable=function-redefined
# def compose(op2: Callable[[B], C], op1: Callable[[A], B]) -> Callable[[A], C]:  # pylint: disable=function-redefined
# def compose(
#     op3: Callable[[C], D], op2: Callable[[B], C], op1: Callable[[A], B]  # pylint: disable=function-redefined
# ) -> Callable[[A], D]:
# def compose(
#     op4: Callable[[D], E],  # pylint: disable=function-redefined
#     op3: Callable[[C], D],
#     op2: Callable[[B], C],
#     op1: Callable[[A], B],
# ) -> Callable[[A], E]:
# def compose(
#     op5: Callable[[E], F],  # pylint: disable=function-redefined
#     op4: Callable[[D], E],
#     op3: Callable[[C], D],
#     op2: Callable[[B], C],
#     op1: Callable[[A], B],
# ) -> Callable[[A], F]:
# def compose(
#     op1: Callable[[A], B],  # pylint: disable=function-redefined,too-many-arguments
#     op2: Callable[[B], C],
#     op3: Callable[[C], D],
#     op4: Callable[[D], E],
#     op5: Callable[[E], F],
#     op6: Callable[[F], G],
# ) -> Callable[[A], G]:
# def compose(*funcs: Callable) -> Callable:  # type: ignore
#     def _compose(source: Any) -> Any:


import unittest
from typing import Callable
from oslash import State
from oslash.util import identity, compose

    def test_state_functor_law_1(self) -> None:
        # fmap id = id
        x = unit(42)

        self.assertEqual(
            x.map(identity).run(state),
            x.run(state)
        )

    def test_state_functor_law2(self) -> None:
        # fmap (f . g) x = fmap f (fmap g x)
        def f(x):
            return x + 10

        def g(x):
            return x * 10

        x : State[int, int] = unit(42)

        self.assertEqual(
            x.map(compose(f, g)).run(state),
            x.map(g).map(f).run(state)
        )


class TestStateMonad(unittest.TestCase):

    def test_state_monad_bind(self) -> None:
        m : State[int, int] = unit(42)

# Path: oslash/state.py
# class State(Generic[TSource, TState]):
#     """The state monad.
# 
#     Wraps stateful computations. A stateful computation is a function
#     that takes a state and returns a result and new state:
# 
#         state -> (result, state')
#     """
# 
#     def __init__(self, fn: Callable[[TState], Tuple[TSource, TState]]) -> None:
#         """Initialize a new state.
# 
#         Keyword arguments:
#         fn -- State processor.
#         """
# 
#         self._fn = fn
# 
#     @classmethod
#     def unit(cls, value: TSource) -> "State[TSource, TState]":
#         r"""Create new State.
# 
#         The unit function creates a new State object wrapping a stateful
#         computation.
# 
#         State $ \s -> (x, s)
#         """
#         return cls(lambda state: (value, state))
# 
#     def map(self, mapper: Callable[[TSource], TResult]) -> "State[TResult, TState]":
#         def _(a: Any, state: Any) -> Tuple[Any, Any]:
#             return mapper(a), state
# 
#         return State(lambda state: _(*self.run(state)))
# 
#     def bind(self, fn: Callable[[TSource], "State[TState, TResult]"]) -> "State[TResult, TState]":
#         r"""m >>= k = State $ \s -> let (a, s') = runState m s
#         in runState (k a) s'
#         """
# 
#         def _(result: Any, state: Any) -> Tuple[Any, Any]:
#             return fn(result).run(state)
# 
#         return State(lambda state: _(*self.run(state)))
# 
#     @classmethod
#     def get(cls) -> "State[TState, TState]":
#         r"""get = state $ \s -> (s, s)"""
#         return State(lambda state: (state, state))
# 
#     @classmethod
#     def put(cls, new_state: TState) -> "State[Tuple, TState]":
#         r"""put newState = state $ \s -> ((), newState)"""
#         return State(lambda state: (Unit, new_state))
# 
#     def run(self, state: TState) -> Tuple[TSource, TState]:
#         """Return wrapped state computation.
# 
#         This is the inverse of unit and returns the wrapped function.
#         """
#         return self._fn(state)
# 
#     def __call__(self, state: Any) -> Tuple:
#         return self.run(state)
# 
# Path: oslash/util/fn.py
# A = TypeVar("A")
# B = TypeVar("B")
# C = TypeVar("C")
# D = TypeVar("D")
# E = TypeVar("E")
# F = TypeVar("F")
# G = TypeVar("G")
# def compose() -> Callable[[A], A]:  # pylint: disable=function-redefined
# def compose(op1: Callable[[A], B]) -> Callable[[A], B]:  # pylint: disable=function-redefined
# def compose(op2: Callable[[B], C], op1: Callable[[A], B]) -> Callable[[A], C]:  # pylint: disable=function-redefined
# def compose(
#     op3: Callable[[C], D], op2: Callable[[B], C], op1: Callable[[A], B]  # pylint: disable=function-redefined
# ) -> Callable[[A], D]:
# def compose(
#     op4: Callable[[D], E],  # pylint: disable=function-redefined
#     op3: Callable[[C], D],
#     op2: Callable[[B], C],
#     op1: Callable[[A], B],
# ) -> Callable[[A], E]:
# def compose(
#     op5: Callable[[E], F],  # pylint: disable=function-redefined
#     op4: Callable[[D], E],
#     op3: Callable[[C], D],
#     op2: Callable[[B], C],
#     op1: Callable[[A], B],
# ) -> Callable[[A], F]:
# def compose(
#     op1: Callable[[A], B],  # pylint: disable=function-redefined,too-many-arguments
#     op2: Callable[[B], C],
#     op3: Callable[[C], D],
#     op4: Callable[[D], E],
#     op5: Callable[[E], F],
#     op6: Callable[[F], G],
# ) -> Callable[[A], G]:
# def compose(*funcs: Callable) -> Callable:  # type: ignore
#     def _compose(source: Any) -> Any:


# Path: tests/test_state.py
import unittest
from typing import Callable
from oslash import State
from oslash.util import identity, compose


    def test_state_functor_law_1(self) -> None:
        # fmap id = id
        x = unit(42)

        self.assertEqual(
            x.map(identity).run(state),
            x.run(state)
        )

    def test_state_functor_law2(self) -> None:
        # fmap (f . g) x = fmap f (fmap g x)
        def f(x):
            return x + 10

        def g(x):
            return x * 10

        x : State[int, int] = unit(42)

        self.assertEqual(
            x.map(compose(f, g)).run(state),
            x.map(g).map(f).run(state)
        )


class TestStateMonad(unittest.TestCase):

    def test_state_monad_bind(self) -> None:
        m : State[int, int] = unit(42)

        f : Callable[[int], State[int, int]]= lambda x: unit(x * 10)