<NME> reader.py
<BEF> from functools import partial

from typing import Callable, Any, TypeVar, Generic

from .typing import Functor
from .typing import Monad
from .typing import Applicative

TEnv = TypeVar("TEnv")
TSource = TypeVar("TSource")
TResult = TypeVar("TResult")


    The Reader monad pass the state you want to share between functions.
    Functions may read that state, but can't change it. The reader monad
    lets us access shared immutable state within a monadic context.
    """

    def __init__(self, fn: Callable):
        r"""Initialize a new reader.

        return a = Reader $ \_ -> a
        """
        self._get_value = lambda: fn

    @classmethod
    def unit(cls, value: Any) -> "Reader":
        """The return function creates a Reader that ignores the
        environment and produces the given value.
        """
        return cls(lambda _: value)

        return cls(lambda _: value)
    def pure(cls, fn: Callable) -> 'Reader':
        return cls.unit(fn)

    def map(self, mapper: Callable[[Any], Any]) -> "Reader":
        r"""fmap f m = Reader $ \r -> f (runReader m r)."""
        func = self.run()

        def _(env):
            try:
                ret = mapper(func(env))
            except TypeError:
                ret = partial(mapper, func(env))
            return ret
        return Reader(_)

    def bind(self, func: "Callable[[Any], Reader]") -> "Reader":
        r"""m >>= k  = Reader $ \r -> runReader (k (runReader m r)) r
        """
        return Reader(lambda r: (func(self.run(r))).run(r))

    def apply(self, something: "Reader") -> "Reader":
        r"""(<*>) :: f (a -> b) -> f a -> f b.

        (R f) <*> (R x) = R $ \e -> (f e) (x e)

        Apply (<*>) is a beefed up fmap. It takes a functor value that
        has a function in it and another functor, and extracts that
        function from the first functor and then maps it over the second
        one.
        """

        func = self.run()
        x = something.run()

        def _(env):
            f = func(env)
            try:
                ret = f(x(env))
            except TypeError:
                ret = partial(f, x(env))
            return ret

        return Reader(_)  # lambda env: f(env)(x(env)))

    def run(self, *args, **kwargs) -> Callable:
        """Return wrapped reader.

        Haskell: runReader :: Reader r a -> r -> a

        This is the inverse of unit and returns the wrapped function.
        If we receive args, we call the function directly to avoid the
        ugly `run()(args)` pattern.
        """
        return self._get_value()(*args, **kwargs) if args else self._get_value()

    def __call__(self, *args, **kwargs) -> Any:
        return self.run(*args, **kwargs)

    def __eq__(self, other) -> bool:
        environment = 0  # TODO: can we do better?
        return self(environment) == other(environment)

    def __str__(self) -> str:
        return "Reader(%s)" % self._get_value()

    def __repr__(self) -> str:
        return str(self)


class MonadReader(Reader):


        Provides a way to easily access the environment.
        ask lets us read the environment and then play with it
        """
        return Reader(lambda x: x)

    @classmethod
    def asks(cls, fn: Callable[[TEnv], TSource]) -> Reader[TEnv, TSource]:
        """
        Given a function it returns a Reader which evaluates that
        function and returns the result.

        asks :: (e -> a) -> R e a
        asks f = do
            e <- ask
            return $ f e

        asks sel = ask >>= return . sel
        """

        return cls.ask().bind(lambda env: cls.unit(fn(env)))

    def local(self, fn: Callable[[TEnv], TEnv]) -> Reader[TEnv, TSource]:
        r"""local transforms the environment a Reader sees.

        local f c = Reader $ \e -> runReader c (f e)
        """
        return Reader(lambda env: self.run(fn(env)))


assert isinstance(Reader, Functor)
assert isinstance(Reader, Applicative)
assert isinstance(Reader, Monad)

<MSG> Callable is Reader :-)

<DFF> @@ -14,19 +14,24 @@ class Reader(Monad, Applicative, Functor):
     The Reader monad pass the state you want to share between functions.
     Functions may read that state, but can't change it. The reader monad
     lets us access shared immutable state within a monadic context.
+
+    The Reader is just a fancy name for function, so this monad could
+    also be called the Function or the Callable monad. It's all about
+    composing functions.
     """
 
     def __init__(self, fn: Callable):
         r"""Initialize a new reader.
 
-        return a = Reader $ \_ -> a
         """
-        self._get_value = lambda: fn
+        self.fn = fn
 
     @classmethod
     def unit(cls, value: Any) -> "Reader":
         """The return function creates a Reader that ignores the
         environment and produces the given value.
+
+        return a = Reader $ \_ -> a
         """
         return cls(lambda _: value)
 
@@ -34,71 +39,83 @@ class Reader(Monad, Applicative, Functor):
     def pure(cls, fn: Callable) -> 'Reader':
         return cls.unit(fn)
 
-    def map(self, mapper: Callable[[Any], Any]) -> "Reader":
-        r"""fmap f m = Reader $ \r -> f (runReader m r)."""
-        func = self.run()
+    def map(self, fn: Callable[[Any], Any]) -> "Reader":
+        r"""Map a function over the Reader.
 
-        def _(env):
+        Haskell:
+        fmap f m = Reader $ \r -> f (runReader m r).
+        fmap f g = (\x -> f (g x))
+        """
+        def _compose(x):
             try:
-                ret = mapper(func(env))
+                ret = fn(self(x))
             except TypeError:
-                ret = partial(mapper, func(env))
+                ret = partial(fn, self(x))
             return ret
-        return Reader(_)
+        return Reader(_compose)
+
+    def bind(self, fn: "Callable[[Any], Reader]") -> "Reader":
+        r"""Bind a monadic function to the Reader.
 
-    def bind(self, func: "Callable[[Any], Reader]") -> "Reader":
-        r"""m >>= k  = Reader $ \r -> runReader (k (runReader m r)) r
+        Haskell:
+        Reader: m >>= k  = Reader $ \r -> runReader (k (runReader m r)) r
+        Function: h >>= f = \w -> f (h w) w
         """
-        return Reader(lambda r: (func(self.run(r))).run(r))
+        return Reader(lambda x: fn(self(x))(x))
 
     def apply(self, something: "Reader") -> "Reader":
         r"""(<*>) :: f (a -> b) -> f a -> f b.
 
-        (R f) <*> (R x) = R $ \e -> (f e) (x e)
+        Haskell: f <*> g = \x -> f x (g x)
 
-        Apply (<*>) is a beefed up fmap. It takes a functor value that
-        has a function in it and another functor, and extracts that
-        function from the first functor and then maps it over the second
-        one.
+        Apply (<*>) is a beefed up map. It takes a Reader that
+        has a function in it and another Reader, and extracts that
+        function from the first Reader and then maps it over the second
+        one (composes the two functions).
         """
 
-        func = self.run()
-        x = something.run()
+        g = something.run()
 
-        def _(env):
-            f = func(env)
+        def _compose(x):
+            f = self(x)
             try:
-                ret = f(x(env))
+                ret = f(g(x))
             except TypeError:
-                ret = partial(f, x(env))
+                ret = partial(f, g(x))
             return ret
 
-        return Reader(_)  # lambda env: f(env)(x(env)))
+        return Reader(_compose)
 
     def run(self, *args, **kwargs) -> Callable:
-        """Return wrapped reader.
+        """Return wrapped function.
 
         Haskell: runReader :: Reader r a -> r -> a
 
         This is the inverse of unit and returns the wrapped function.
-        If we receive args, we call the function directly to avoid the
-        ugly `run()(args)` pattern.
         """
-        return self._get_value()(*args, **kwargs) if args else self._get_value()
+        return self(*args, **kwargs)
 
     def __call__(self, *args, **kwargs) -> Any:
-        return self.run(*args, **kwargs)
+        """Call the wrapped function."""
+        return self.fn(*args, **kwargs) if args or kwargs else self.fn
 
     def __eq__(self, other) -> bool:
-        environment = 0  # TODO: can we do better?
-        return self(environment) == other(environment)
+        environment = 42  # Can't be wrong!
+        try:
+            equal = self(environment) == other(environment)
+        except Exception:
+            equal = False
+        return equal
 
     def __str__(self) -> str:
-        return "Reader(%s)" % self._get_value()
+        return "Reader(%s)" % self.fn()
 
     def __repr__(self) -> str:
         return str(self)
 
+# Our version of underscore
+_ = Reader
+
 
 class MonadReader(Reader):
 

Callable is Reader :-)