# -*- coding: utf-8 -*-
# Copyright (c) 2012-2014, Philip Xu <pyx@xrefactor.com>
# License: BSD New, see LICENSE for details.
"""monad.types.list - The List Monad."""
from collections import Sequence
from itertools import chain
from . import LazySequence, MonadPlus
from ..mixins import Ord
[docs]class List(MonadPlus, Ord, Sequence):
"""The List Monad.
Representing nondeterministic computation.
>>> List(42)
List(42)
>>> List(1, 2, 3)
List(1, 2, 3)
>>> List([])
List([])
>>> List.from_iterable(range(3))
List(0, 1, 2)
>>> List.from_iterable(n for n in (1, 2, 3) if n % 2 == 0)
List(2)
>>> List(List(2))
List(List(2))
Lists are lazy
>>> from itertools import count
>>> m = List.from_iterable(count())
>>> m[:5]
List(0, 1, 2, 3, 4)
>>> m[520:524]
List(520, 521, 522, 523)
>>> list(m[1000:1002])
[1000, 1001]
Bind operation with ``>>``
>>> spawn = lambda cell: List(cell, cell)
>>> spawn('c')
List('c', 'c')
>>> spawn('c') >> spawn
List('c', 'c', 'c', 'c')
>>> grow = lambda cell: List(cell + '~')
>>> grow('o')
List('o~')
>>> grow('o') >> grow >> grow >> grow
List('o~~~~')
>>> generation = lambda cell: grow(cell) + spawn(cell)
>>> first = List('o')
>>> first
List('o')
>>> first >> generation
List('o~', 'o', 'o')
>>> first >> generation >> generation
List('o~~', 'o~', 'o~', 'o~', 'o', 'o', 'o~', 'o', 'o')
"""
# pylint: disable = too-many-ancestors
def __init__(self, *items):
super(List, self).__init__(LazySequence(items))
def __getitem__(self, index):
items = self.value.__getitem__(index)
if isinstance(index, slice):
return self.from_iterable(items)
return items
def __len__(self):
return len(self.value)
def __nonzero__(self):
return len(self.value)
def __repr__(self):
"""Customized Show."""
return 'List({})'.format(', '.join(repr(x) for x in self))
[docs] @classmethod
def from_iterable(cls, iterator):
"""Creates ``List`` from iterable."""
instance = cls.unit()
instance.value = LazySequence(iterator)
return instance
[docs] def fmap(self, function):
"""fmap of List Monad."""
return self.from_iterable(function(i) for i in self)
[docs] def join(self):
"""join of List Monad."""
return self.from_iterable(chain.from_iterable(self))
[docs] def plus(self, monad):
"""plus operation, concatenates two ``List``."""
if not isinstance(monad, type(self)):
return NotImplemented
return self.from_iterable(chain(self, monad))
List.zero = List()