def test_build_sig_item(self): """Test type signature building internals - make sure that types are translated in a reasonable way""" class example: pass # type variables self.assertTrue(isinstance(build_sig_arg("a", {}, {}), TypeVariable)) self.assertTrue(isinstance(build_sig_arg("abc", {}, {}), TypeVariable)) # builtin/non-ADT types self.unified(build_sig_arg(str, {}, {}), TypeOperator(str, [])) self.unified(build_sig_arg(int, {}, {}), TypeOperator(int, [])) self.unified(build_sig_arg(float, {}, {}), TypeOperator(float, [])) self.unified(build_sig_arg(list, {}, {}), TypeOperator(list, [])) self.unified(build_sig_arg(set, {}, {}), TypeOperator(set, [])) self.unified(build_sig_arg(example, {}, {}), TypeOperator(example, [])) # unit type (None) self.unified(build_sig_arg(None, {}, {}), TypeOperator(None, [])) # tuple self.unified(build_sig_arg((int, int), {}, {}), Tuple([TypeOperator(int, []), TypeOperator(int, [])])) self.unified( build_sig_arg((None, (None, int)), {}, {}), Tuple([ TypeOperator(None, []), Tuple([TypeOperator(None, []), TypeOperator(int, [])]) ])) a = TypeVariable() self.unified(build_sig_arg(("a", "a", "a"), {}, {}), Tuple([a, a, a])) # list self.unified(typeof(L[[]]), build_sig_arg(["a"], {}, {})) self.unified(typeof(L[1, 1]), build_sig_arg([int], {}, {})) self.unified(typeof(L[[L[1, 1]]]), build_sig_arg([[int]], {}, {})) # adts self.unified(typeof(Nothing), build_sig_arg(t(Maybe, "a"), {}, {})) self.unified(typeof(Just(1)), build_sig_arg(t(Maybe, int), {}, {})) self.unified(typeof(Just(Just(Nothing))), build_sig_arg(t(Maybe, t(Maybe, t(Maybe, "a"))), {}, {})) self.unified(typeof(Right("error")), build_sig_arg(t(Either, str, "a"), {}, {})) self.unified(typeof(Left(2.0)), build_sig_arg(t(Either, "a", int), {}, {})) self.unified(typeof(Just(__ + 1)), build_sig_arg(t(Maybe, "a"), {}, {})) self.unified(typeof(Just(__ + 1)), build_sig_arg(t(Maybe, (H / "a" >> "b")), {}, {}))
def __next(self): """Evaluate the next element of the tail, and add it to the head.""" from hask3.lang.type_system import typeof from hask3.lang.hindley_milner import unify 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
def __rxor__(self, item): """``^`` is the ``cons`` operator (equivalent to ``:`` in Haskell).""" from hask3.lang.type_system import typeof from hask3.lang.hindley_milner import ListType, unify 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 __init__(self, head=None, tail=None): from itertools import chain from hask3.lang.type_system import typeof from hask3.lang.hindley_milner import unify if head is not None: count = len(head) if count > 0: fst = head[0] i = 1 while i < count: unify(typeof(fst), typeof(head[i])) i += 1 self.__head = list(head) else: self.__head = [] self.__is_evaluated = tail is None self.__tail = chain([] if self.__is_evaluated else tail)
def test_typecheck_builtins(self): """Make sure builtin types typecheck correctly""" # 1 :: int self.unified(typeof(1), TypeOperator(int, [])) # "a" :: str self.unified(typeof("a"), TypeOperator(str, [])) # Nothing :: Maybe a self.unified(typeof(Nothing), TypeOperator(Maybe, [TypeVariable()])) # Just(1) :: Maybe int self.unified(typeof(Just(1)), TypeOperator(Maybe, [TypeOperator(int, [])])) # Just(Just(Nothing)) :: Maybe (Maybe (Maybe a)) self.unified( typeof(Just(Just(Nothing))), TypeOperator( Maybe, [TypeOperator(Maybe, [TypeOperator(Maybe, [TypeVariable()])]) ])) # Right("error") :: Either a str self.unified( typeof(Right("error")), TypeOperator( Either, [TypeVariable(), TypeOperator(str, [])])) # Left(2.0) :: Either float a self.unified( typeof(Left(2.0)), TypeOperator(Either, [TypeOperator(float, []), TypeVariable()]))
def __type__(self): from hask3.lang.type_system import typeof from hask3.lang.hindley_milner import TypeVariable, ListType if len(self.__head) == 0: if self.__is_evaluated: return ListType(TypeVariable()) else: self.__next() return self.__type__() else: return ListType(typeof(self[0]))
def __add__(self, other): """``(+) :: [a] -> [a] -> [a]`` ``+`` is the list concatenation operator, equivalent to ``++`` in Haskell and + for Python lists """ from itertools import chain from hask3.lang.type_system import typeof from hask3.lang.hindley_milner import unify 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) else: return List(head=self.__head, tail=chain(self.__tail, other))
def _t(obj): """Returns a string representing the type of an object. Includes higher-kinded types and ADTs. Equivalent to ``:t`` in Haskell. Meant to be used in the REPL, but might also be useful for debugging. :param obj: the object to inspect. :returns: A string representation of the type. Usage:: >>> from hask3 import _t >>> _t(1) 'int' >>> _t(Just("hello world")) '(Maybe str)' """ from hask3.lang.type_system import typeof return str(typeof(obj))
def __contains__(self, x): from hask3.hack import isin from hask3.lang.type_system import typeof from hask3.lang.hindley_milner import ListType, unify unify(self.__type__(), ListType(typeof(x))) return isin(x, iter(self))
def index(self, x): from hask3.lang.type_system import typeof from hask3.lang.hindley_milner import ListType, unify unify(self.__type__(), ListType(typeof(x))) self.__evaluate() return self.__head.index(x)