def __type__(self): if self.__is_evaluated: if len(self.__head) == 0: return ListType(TypeVariable()) return ListType(typeof(self[0])) elif len(self.__head) == 0: self.__next() return self.__type__() return ListType(typeof(self[0]))
def __init__(self, head=None, tail=None): self.__head = [] self.__tail = itertools.chain([]) self.__is_evaluated = True if head is not None and len(head) > 0: fst = head[0] for fst, other in zip(itertools.repeat(fst), head): unify(typeof(fst), typeof(other)) self.__head.extend(head) if tail is not None: self.__tail = itertools.chain(self.__tail, tail) self.__is_evaluated = False return
def __next(self): """ Evaluate the next element of the tail, and add it to the head. """ if self.__is_evaluated: raise StopIteration else: try: next_iter = next(self.__tail) if len(self.__head) > 0: unify(typeof(self[0]), typeof(next_iter)) self.__head.append(next_iter) except StopIteration: self.__is_evaluated = True return
def __rxor__(self, item): """ ^ is the cons operator (equivalent to : in Haskell) """ unify(self.__type__(), ListType(typeof(item))) if self.__is_evaluated: return List(head=[item] + self.__head) return List(head=[item] + self.__head, tail=self.__tail)
def __add__(self, other): """ (+) :: [a] -> [a] -> [a] + is the list concatenation operator, equivalent to ++ in Haskell and + for Python lists """ unify(self.__type__(), typeof(other)) if self.__is_evaluated and other.__is_evaluated: return List(head=self.__head + other.__head) elif self.__is_evaluated and not other.__is_evaluated: return List(head=self.__head + other.__head, tail=other.__tail) return List(head=self.__head, tail=itertools.chain(self.__tail, iter(other)))
def _t(obj): """ Returns a string representing the type of an object, including higher-kinded types and ADTs. Equivalent to `:t` in Haskell. Meant to be used in the REPL, but might also be useful for debugging. Args: obj: the object to inspect Returns: A string representation of the type Usage: >>> _t(1) int >>> _t(Just("hello world")) Maybe str """ return str(typeof(obj))
def __contains__(self, x): unify(self.__type__(), ListType(typeof(x))) for item in iter(self): if item is x: return True return False
def index(self, x): unify(self.__type__(), ListType(typeof(x))) self.__evaluate() return self.__head.index(x)
def count(self, x): unify(self.__type__(), ListType(typeof(x))) self.__evaluate() return self.__head.count(x)