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

from typing import Any, Callable, Iterator

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

TSource = TypeVar("TSource")
TResult = TypeVar("TResult")
TSelector = Callable[[TSource, 'List[TSource]'], Union[TSource, 'List[TSource]']]


    Wraps an immutable list built from lambda expressions.
    """

    def __init__(self, xs=None, fn=None):
        if xs and not isinstance(xs, List):
            # Builds List from iterable using cons only
            l = List(xs[1:]).cons(xs[0])
            fn = l._get_value()

        self._get_value = lambda: fn

    def cons(self, value):
        xs = self._get_value()
        return List(fn=lambda fn_: fn_(value, xs))

    def head(self):
        xs = self._get_value()
        return xs(lambda x, _: x)

    def tail(self):
        xs = self._get_value()
        return List(fn=xs(lambda _, xs_: xs_))

    def null(self):
        return not self._get_value()

    @classmethod
    def unit(cls, value):
        """ Wraps a value within the singleton list"""
        return cls().cons(value)
    pure = unit
        Fold a list using the monoid. For most types, the default
        definition for mconcat will be used, but the function is
        included in the class definition so that an optimized version
        can be provided for specific types.
        """

        def reducer(a, b):
            return a + b

        return reduce(reducer, xs, Nil())

    @abstractmethod
    def head(self) -> TSource:
        raise NotImplementedError

    @abstractmethod
    def tail(self) -> 'List[TSource]':

    @classmethod
    def empty(cls) -> 'List':
        """Create an empty list"""
        return cls([])

    def append(self, other: 'List'):
        """Append a list to this list"""
        return List(list(self) + list(other))

    def bind(self, func: Callable[[Any], 'List']) -> 'List':
        # xs >>= f = concat (map f xs)
        return List.concat(self.map(func))  # aka flat_map

    def __iter__(self) -> Iterator:
        xs = self  # Don't think we can avoid this mutable local
        while True:
            if xs.null():

    @abstractmethod
    def null(self) -> bool:
        """Return True if List is empty."""
        raise NotImplementedError

    @abstractmethod
    def __add__(self, other):
        raise NotImplementedError
        return str(self)

    def __eq__(self, other: 'List') -> bool:
        return [x for x in self] == [y for y in other]
    def __init__(self, run: Callable[[TSelector], Union[TSource, List[TSource]]]) -> None:
        """Initialize List."""

        self._list = run

    def cons(self, element: TSource) -> List[TSource]:
        """Add element to front of List."""

        return Cons(lambda sel: sel(element, self))

    def head(self) -> TSource:
        """Retrive first element in List."""

        run = self._list
        return cast(TSource, run(lambda head, _: head))

    def tail(self) -> 'List[TSource]':
        """Return tail of List."""

        run = self._list
        return cast(List[TSource], run(lambda _, tail: tail))

    def null(self) -> bool:
        """Return True if List is empty."""
        return False

    def map(self, mapper: Callable[[TSource], TResult]) -> List[TResult]:
        """Map a function over a List."""
        return (self.tail().map(mapper)).cons(mapper(self.head()))

    def apply(self, something: 'List') -> 'List':
        # fs <*> xs = [f x | f <- fs, x <- xs]
        try:
            xs = [f(x) for f in self for x in something]
        except TypeError:
            xs = [partial(f, x) for f in self for x in something]

        return List.from_iterable(xs)

    def append(self, other: List[TSource]) -> List[TSource]:
        """Append other list to this list."""

        return (self.tail().append(other)).cons(self.head())

    def bind(self, fn: Callable[[TSource], List[TResult]]) -> List[TResult]:
        """Flatten and map the List.

        Haskell: xs >>= f = concat (map f xs)
        """
        return List.concat(self.map(fn))

    def __iter__(self) -> Iterator:
        """Return iterator for List."""

        yield self.head()
        yield from self.tail()

    def __or__(self, func):
        """Use | as operator for bind.

        Provide the | operator instead of the Haskell >>= operator
        """
        return self.bind(func)

    def __rshift__(self, next):
        """The "Then" operator.

        Sequentially compose two monadic actions, discarding any value
        produced by the first, like sequencing operators (such as the
        semicolon) in imperative languages.

        Haskell: (>>) :: m a -> m b -> m b
        """
        return self.bind(lambda _: next)

    def __add__(self, other):
        return self.append(other)

    def __len__(self) -> int:
        """Return length of List."""

        return 1 + len(self.tail())

    def __str__(self) -> str:
        """Return string representation of List."""

        return "[%s]" % ", ".join([str(x) for x in self])

    def __repr__(self) -> str:
        """Return string representation of List."""

        return str(self)

    def __eq__(self, other) -> bool:
        """Compare if List is equal to other List."""

        if isinstance(other, Nil):
            return False
        return self.head() == other.head() and self.tail() == other.tail()


class Nil(List[TSource]):
    def __init__(self) -> None:
        """Initialize List."""
        pass

    def cons(self, element: TSource) -> 'List[TSource]':
        """Add element to front of List."""

        return Cons(lambda sel: sel(element, Nil()))

    def head(self) -> TSource:
        """Retrive first element in List."""

        raise IndexError("List is empty")

    def tail(self) -> 'List[TSource]':
        """Return tail of List."""

        raise IndexError("List is empty")

    def null(self) -> bool:
        """Return True if List is empty."""
        return True

    def map(self, mapper: Callable[[TSource], TResult]) -> List[TResult]:
        """Map a function over a List."""
        return Nil()

    def apply(self, something: 'List') -> 'List':
        # fs <*> xs = [f x | f <- fs, x <- xs]
        try:
            xs = [f(x) for f in self for x in something]
        except TypeError:
            xs = [partial(f, x) for f in self for x in something]

        return List.from_iterable(xs)

    def append(self, other: List[TSource]) -> List[TSource]:
        """Append other list to this list."""

        if self.null():
            return other
        return (self.tail().append(other)).cons(self.head())

    def bind(self, fn: Callable[[TSource], List[TResult]]) -> List[TResult]:
        """Flatten and map the List.

        Haskell: xs >>= f = concat (map f xs)
        """
        return List.concat(self.map(fn))

    def __iter__(self) -> Iterator:
        """Return iterator for List."""

        while False:
            yield

    def __or__(self, func):
        """Use | as operator for bind.

        Provide the | operator instead of the Haskell >>= operator
        """
        return self.bind(func)

    def __rshift__(self, next):
        """The "Then" operator.

        Sequentially compose two monadic actions, discarding any value
        produced by the first, like sequencing operators (such as the
        semicolon) in imperative languages.

        Haskell: (>>) :: m a -> m b -> m b
        """
        return self.bind(lambda _: next)

    def __add__(self, other):
        return self.append(other)

    def __len__(self) -> int:
        """Return length of List."""

        return 0

    def __str__(self) -> str:
        """Return string representation of List."""

        return "[%s]" % ", ".join([str(x) for x in self])

    def __repr__(self) -> str:
        """Return string representation of List."""

        return str(self)

    def __eq__(self, other) -> bool:
        """Compare if List is equal to other List."""

        return True if isinstance(other, Nil) else False


assert(isinstance(List, Monoid))
assert(isinstance(List, Functor))
assert(isinstance(List, Applicative))
assert(isinstance(List, Monad))

assert(isinstance(Cons, Monoid))
assert(isinstance(Cons, Functor))
assert(isinstance(Cons, Applicative))
assert(isinstance(Cons, Monad))

assert(isinstance(Nil, Monoid))
assert(isinstance(Nil, Functor))
assert(isinstance(Nil, Applicative))
assert(isinstance(Nil, Monad))

<MSG> Refactored list

<DFF> @@ -1,3 +1,4 @@
+import collections
 from functools import partial
 
 from typing import Any, Callable, Iterator
@@ -15,31 +16,37 @@ class List(Monad, Monoid, Applicative, Functor):
     Wraps an immutable list built from lambda expressions.
     """
 
-    def __init__(self, xs=None, fn=None):
-        if xs and not isinstance(xs, List):
-            # Builds List from iterable using cons only
-            l = List(xs[1:]).cons(xs[0])
-            fn = l._get_value()
-
-        self._get_value = lambda: fn
-
-    def cons(self, value):
-        xs = self._get_value()
-        return List(fn=lambda fn_: fn_(value, xs))
-
-    def head(self):
-        xs = self._get_value()
-        return xs(lambda x, _: x)
-
-    def tail(self):
-        xs = self._get_value()
-        return List(fn=xs(lambda _, xs_: xs_))
-
-    def null(self):
+    def __init__(self, lambda_list: Callable[[Callable], Any]=None):
+        """Initialize List."""
+        # Accept building List from a Python iterable
+        if isinstance(lambda_list, collections.Iterable):
+            # Partially build List from iterable using cons only
+            l = List(lambda_list[1:]).cons(lambda_list[0]) if lambda_list else List()
+            lambda_list = l._get_value()
+
+        self._get_value = lambda: lambda_list
+
+    def cons(self, element: Any) -> 'List':
+        """Append element to List."""
+        lambda_list = self._get_value()
+        return List(lambda sel: sel(element, lambda_list))
+
+    def head(self) -> Any:
+        """Retrive first element in List."""
+        lambda_list = self._get_value()
+        return lambda_list(lambda head, _: head)
+
+    def tail(self) -> 'List':
+        """Return tail of List."""
+        lambda_list = self._get_value()
+        return List(lambda_list(lambda _, tail: tail))
+
+    def null(self) -> bool:
+        """Return True if List is emtpty."""
         return not self._get_value()
 
     @classmethod
-    def unit(cls, value):
+    def unit(cls, value: Any):
         """ Wraps a value within the singleton list"""
         return cls().cons(value)
     pure = unit
@@ -63,18 +70,22 @@ class List(Monad, Monoid, Applicative, Functor):
 
     @classmethod
     def empty(cls) -> 'List':
-        """Create an empty list"""
-        return cls([])
+        """Create an empty list."""
+        return cls()
 
     def append(self, other: 'List'):
-        """Append a list to this list"""
+        """Append a list to this list."""
         return List(list(self) + list(other))
 
-    def bind(self, func: Callable[[Any], 'List']) -> 'List':
-        # xs >>= f = concat (map f xs)
-        return List.concat(self.map(func))  # aka flat_map
+    def bind(self, fn: Callable[[Any], 'List']) -> 'List':
+        """Flatten and map the List.
+
+        Haskell: xs >>= f = concat (map f xs)
+        """
+        return List.concat(self.map(fn))
 
     def __iter__(self) -> Iterator:
+        """Return iterator for List."""
         xs = self  # Don't think we can avoid this mutable local
         while True:
             if xs.null():
@@ -90,4 +101,5 @@ class List(Monad, Monoid, Applicative, Functor):
         return str(self)
 
     def __eq__(self, other: 'List') -> bool:
+        """Compare if List is equal to other List."""
         return [x for x in self] == [y for y in other]

Refactored list