<NME> test_reader.py
<BEF> import unittest

from oslash import Reader
from oslash.reader import MonadReader
from oslash.util import identity, compose, fmap

pure = Reader.pure
unit = Reader.unit
asks = MonadReader.asks


class TestReader(unittest.TestCase):

    def test_reader_run(self):
        r = Reader(lambda name: "Hello, %s!" % name)
        greeting = r.run()("adit")
        self.assertEqual(greeting, "Hello, adit!")

    def test_reader_asks(self):
        a = asks(len).run()("Banana")
        self.assertEqual(6, a)


class TestReaderFunctor(unittest.TestCase):

    def test_reader_functor_map(self):
        x = unit(42)
        f = lambda x: x * 10

        f = lambda x: x * 10

            unit(420)
        )

    def test_reader_functor_law_1(self):
        # fmap id = id
        x = unit(42)

        x = unit(42)

            x
        )

    def test_reader_functor_law2(self):
        # fmap (f . g) x = fmap f (fmap g x)
        def f(x):
            return x+10
        def f(x):
            return x+10

        def g(x):
            return x*10

        x = unit(42)

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

class TestReaderApplicative(unittest.TestCase):

    def test_reader_applicative_law_functor(self):
        # pure f <*> x = fmap f x
        x = unit(42)
        f = lambda e: e * 42
        x = unit(42)
        f = lambda e: e * 42

            x.map(f)
        )

    def test_reader_applicative_law_identity(self):
        # pure id <*> v = v
        v = unit(42)

        v = unit(42)

            v
        )

    def test_reader_applicative_law_composition(self):
        # pure (.) <*> u <*> v <*> w = u <*> (v <*> w)

        w = unit(42)

        w = unit(42)
        u = pure(lambda x: x * 42)
        v = pure(lambda x: x + 42)

            u.apply(v.apply(w))
        )

    def test_reader_applicative_law_homomorphism(self):
        # pure f <*> pure x = pure (f x)
        x = 42
        f = lambda x: x * 42
        x = 42
        f = lambda x: x * 42

            unit(f(x))
        )

    def test_reader_applicative_law_interchange(self):
        # u <*> pure y = pure ($ y) <*> u

        y = 43

        y = 43
        u = pure(lambda x: x*42)

        self.assertEqual(
            u.apply(unit(y)).run(env),
            pure(lambda f: f(y)).apply(u).run(env)

class TestReaderMonad(unittest.TestCase):

    def test_reader_monad_bind(self):
        m = unit(42)
        f = lambda x: unit(x*10)

        f = lambda x: unit(x*10)

            unit(420)
        )

    def test_reader_monad_law_left_identity(self):
        # return x >>= f is the same thing as f x

        f = lambda x: unit(x+100000)

        f = lambda x: unit(x+100000)
        x = 3

            f(x)
        )

    def test_reader_monad_law_right_identity(self):
        # m >>= return is no different than just m.

        m = unit("move on up")

        m = unit("move on up")

            m
        )

    def test_reader_monad_law_associativity(self):
        # (m >>= f) >>= g is just like doing m >>= (\x -> f x >>= g)
        m = unit(42)
        f = lambda x: unit(x+1000)
        m = unit(42)
        f = lambda x: unit(x+1000)
        g = lambda y: unit(y*42)

        self.assertEqual(
            m.bind(f).bind(g).run(env),
            m.bind(lambda x: f(x).bind(g)).run(env)
        )

<MSG> Simplified typing. Cannot be properly typed using Generics anyway.

<DFF> @@ -11,19 +11,19 @@ asks = MonadReader.asks
 
 class TestReader(unittest.TestCase):
 
-    def test_reader_run(self):
+    def test_reader_run(self) -> None:
         r = Reader(lambda name: "Hello, %s!" % name)
         greeting = r.run()("adit")
         self.assertEqual(greeting, "Hello, adit!")
 
-    def test_reader_asks(self):
-        a = asks(len).run()("Banana")
+    def test_reader_asks(self) -> None:
+        a = asks(len).run("Banana")
         self.assertEqual(6, a)
 
 
 class TestReaderFunctor(unittest.TestCase):
 
-    def test_reader_functor_map(self):
+    def test_reader_functor_map(self) -> None:
         x = unit(42)
         f = lambda x: x * 10
 
@@ -32,7 +32,7 @@ class TestReaderFunctor(unittest.TestCase):
             unit(420)
         )
 
-    def test_reader_functor_law_1(self):
+    def test_reader_functor_law_1(self) -> None:
         # fmap id = id
         x = unit(42)
 
@@ -41,7 +41,7 @@ class TestReaderFunctor(unittest.TestCase):
             x
         )
 
-    def test_reader_functor_law2(self):
+    def test_reader_functor_law2(self) -> None:
         # fmap (f . g) x = fmap f (fmap g x)
         def f(x):
             return x+10
@@ -59,7 +59,7 @@ class TestReaderFunctor(unittest.TestCase):
 
 class TestReaderApplicative(unittest.TestCase):
 
-    def test_reader_applicative_law_functor(self):
+    def test_reader_applicative_law_functor(self) -> None:
         # pure f <*> x = fmap f x
         x = unit(42)
         f = lambda e: e * 42
@@ -69,7 +69,7 @@ class TestReaderApplicative(unittest.TestCase):
             x.map(f)
         )
 
-    def test_reader_applicative_law_identity(self):
+    def test_reader_applicative_law_identity(self) -> None:
         # pure id <*> v = v
         v = unit(42)
 
@@ -78,7 +78,7 @@ class TestReaderApplicative(unittest.TestCase):
             v
         )
 
-    def test_reader_applicative_law_composition(self):
+    def test_reader_applicative_law_composition(self) -> None:
         # pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
 
         w = unit(42)
@@ -90,7 +90,7 @@ class TestReaderApplicative(unittest.TestCase):
             u.apply(v.apply(w))
         )
 
-    def test_reader_applicative_law_homomorphism(self):
+    def test_reader_applicative_law_homomorphism(self) -> None:
         # pure f <*> pure x = pure (f x)
         x = 42
         f = lambda x: x * 42
@@ -100,7 +100,7 @@ class TestReaderApplicative(unittest.TestCase):
             unit(f(x))
         )
 
-    def test_reader_applicative_law_interchange(self):
+    def test_reader_applicative_law_interchange(self) -> None:
         # u <*> pure y = pure ($ y) <*> u
 
         y = 43
@@ -114,7 +114,7 @@ class TestReaderApplicative(unittest.TestCase):
 
 class TestReaderMonad(unittest.TestCase):
 
-    def test_reader_monad_bind(self):
+    def test_reader_monad_bind(self) -> None:
         m = unit(42)
         f = lambda x: unit(x*10)
 
@@ -123,7 +123,7 @@ class TestReaderMonad(unittest.TestCase):
             unit(420)
         )
 
-    def test_reader_monad_law_left_identity(self):
+    def test_reader_monad_law_left_identity(self) -> None:
         # return x >>= f is the same thing as f x
 
         f = lambda x: unit(x+100000)
@@ -134,7 +134,7 @@ class TestReaderMonad(unittest.TestCase):
             f(x)
         )
 
-    def test_reader_monad_law_right_identity(self):
+    def test_reader_monad_law_right_identity(self) -> None:
         # m >>= return is no different than just m.
 
         m = unit("move on up")
@@ -144,7 +144,7 @@ class TestReaderMonad(unittest.TestCase):
             m
         )
 
-    def test_reader_monad_law_associativity(self):
+    def test_reader_monad_law_associativity(self) -> None:
         # (m >>= f) >>= g is just like doing m >>= (\x -> f x >>= g)
         m = unit(42)
         f = lambda x: unit(x+1000)

Simplified typing. Cannot be properly typed using Generics anyway.