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 __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 __call__(self, *args, **kwargs): # the environment contains the type of the function and the types # of the arguments env = {id(self):self.fn_type} env.update({id(arg):typeof(arg) for arg in args}) ap = Var(id(self)) for arg in args: if isinstance(arg, Undefined): return arg ap = App(ap, Var(id(arg))) result_type = analyze(ap, env) if len(self.fn_args) - 1 == len(args): result = self.func(*args) unify(result_type, typeof(result)) return result return TypedFunc(functools.partial(self.func, *args, **kwargs), self.fn_args[len(args):], result_type)
def __call__(self, *args, **kwargs): # the environment contains the type of the function and the types # of the arguments env = {id(self): self.fn_type} env.update({id(arg): typeof(arg) for arg in args}) ap = Var(id(self)) for arg in args: if isinstance(arg, Undefined): return arg ap = App(ap, Var(id(arg))) result_type = analyze(ap, env) if len(self.fn_args) - 1 == len(args): result = self.func(*args) unify(result_type, typeof(result)) return result return TypedFunc(functools.partial(self.func, *args, **kwargs), self.fn_args[len(args):], result_type)
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)