def test_monad(self): f = (lambda x: Just(str(x)))**(H / int >> t(Maybe, str)) g = (lambda x: Just(x * 10))**(H / int >> t(Maybe, int)) self.assertEqual(Just("1"), Just(1) >> f) self.assertEqual(Just(10), Just(1) >> g) self.assertEqual(Just(1000), Just(1) >> g >> g >> g) @sig(H[(Num, "a")] / "a" >> "a" >> t(Maybe, "a")) def safediv(x, y): return Just(x // y) if y != 0 else Nothing from hask3.Prelude import flip s = flip(safediv) self.assertEqual(Just(3), Just(9) >> s(3)) self.assertEqual(Just(1), Just(9) >> s(3) >> s(3)) self.assertEqual(Nothing, Just(9) >> s(0) >> s(3)) self.assertEqual(Nothing, Nothing >> s(3) >> s(3)) # monad laws s_composed = (lambda x: s(3, x) >> s(3))**(H / int >> t(Maybe, int)) self.assertEqual(Just(2), Just(2) >> Just) self.assertEqual(Nothing, Nothing >> Just) self.assertEqual(Just(4) >> s(2), s(2, 4)) self.assertEqual(Just(1), (Just(9) >> s(3)) >> s(3)) self.assertEqual(Just(1), Just(9) >> s_composed) self.assertEqual(Nothing, (Nothing >> s(3)) >> s(3)) self.assertEqual(Nothing, Nothing >> s_composed) from hask3.Control.Monad import join, liftM self.assertEqual(join(Just(Just(1))), Just(1)) self.assertEqual(join(Just(Nothing)), Nothing) self.assertEqual(liftM(__ + 1, Just(1)), Just(2)) self.assertEqual(liftM(__ + 1, Nothing), Nothing)
def test_monad(self): from hask3.Prelude import flip from hask3.Control.Monad import bind, join @sig(H/ int >> int >> t(Either, str, int)) def sub_whole(x, y): return Right(x-y) if (x-y) >= 0 else Left("err") sub = flip(sub_whole) self.assertEqual(Right(2), Right(4) >> sub(2)) self.assertEqual(Right(0), Right(4) >> sub(2) >> sub(2)) self.assertEqual(Left("err"), Right(4) >> sub(10)) self.assertEqual(Left("0"), Left("0") >> sub_whole(1)) # monad laws sub_composed = (lambda x: sub_whole(4, x) >> sub(2)) ** \ (H/ int >> t(Either, "a", int)) self.assertEqual(Right(7), Right(7) >> Right) self.assertEqual(Left(7), Left(7) >> Right) self.assertEqual(Right(1), (Right(5) >> sub(1)) >> sub(3)) self.assertEqual(Left("e"), (Left("e") >> sub(1)) >> sub(3)) self.assertEqual(Left("err"), (Right(5) >> sub(10)) >> sub(3)) self.assertEqual(Right(0), Right(2) >> sub_composed) self.assertEqual(Left("e"), Left("e") >> sub_composed) self.assertEqual(Right(2), bind(Right(4), sub(2))) self.assertEqual(join(Right(Right(1))), Right(1)) self.assertEqual(join(Right(Left(1))), Left(1))
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 test_typeclasses(self): from hask3.Prelude import fmap M, N, J = data.M("a") == d.N | d.J("a") & deriving(Show, Eq, Ord) def maybe_fmap(fn, maybe_value): return ~(caseof(maybe_value) | m(N) >> N | m(J(m.x)) >> J(fn(p.x)) ) instance(Functor, M).where( fmap = maybe_fmap ) times2 = (lambda x: x * 2) ** (H/ int >> int) toFloat = float ** (H/ int >> float) self.assertEqual(fmap(toFloat, J(10)), J(10.0)) self.assertEqual(fmap(toFloat, fmap(times2, J(25))), J(50.0)) self.assertEqual((toFloat * times2) * J(25), J(50.0)) self.assertEqual((toFloat * times2) * N, N) instance(Applicative, M).where( pure = J ) instance(Monad, M).where( bind = lambda x, f: ~(caseof(x) | m(J(m.a)) >> f(p.a) | m(N) >> N) ) @sig(H/ int >> int >> t(M, int)) def safe_div(x, y): return N if y == 0 else J(x//y) from hask3.Prelude import flip divBy = flip(safe_div) self.assertEqual(J(9) >> divBy(3), J(3)) self.assertEqual(Just(12) >> divBy(2) >> divBy(2) >> divBy(3), J(1)) self.assertEqual(J(12) >> divBy(0) >> divBy(6), N) from hask3.Data.List import replicate self.assertEqual(L[1, 2] >> replicate(2) >> replicate(2), L[1, 1, 1, 1, 2, 2, 2, 2]) class Person: def __init__(self, name, age): self.name = name self.age = age instance(Eq, Person).where( eq = lambda p1, p2: p1.name == p2.name and p1.age == p2.age ) self.assertFalse(Person("Philip Wadler", 59) == Person("Simon Peyton Jones", 57))
def test_building_lists(self): from hask3.Data.List import scanl, scanl1, scanr, scanr1, mapAccumL # noqa: F401 from hask3.Data.List import mapAccumR, iterate, repeat, replicate, cycle # noqa: F401 from hask3.Data.List import unfoldr plus_one = (lambda x: x + 1)**(H / int >> int) self.assertEquals(iterate(plus_one, 0)[:10], L[range(10)]) self.assertEquals(iterate(__ + 1, 0)[:10], L[range(10)]) uf = (lambda x: Nothing if x > 5 else Just((x+1, x+1))) ** \ (H/ int >> t(Maybe, (int, int))) self.assertEquals(L[[]], unfoldr(uf, 6)) self.assertEquals(L[1, ..., 6], unfoldr(uf, 0))
def test_functions(self): from hask3.Data.Maybe import maybe, isJust, isNothing, fromJust from hask3.Data.Maybe import fromMaybe from hask3.Data.Maybe import listToMaybe, maybeToList, catMaybes from hask3.Data.Maybe import mapMaybe self.assertTrue(isJust(Just(1))) self.assertTrue(isJust(Just(Nothing))) self.assertFalse(isJust(Nothing)) self.assertFalse(isNothing(Just(1))) self.assertFalse(isNothing(Just(Nothing))) self.assertTrue(isNothing(Nothing)) self.assertEqual(fromJust(Just("bird")), "bird") self.assertEqual(fromJust(Just(Nothing)), Nothing) with self.assertRaises(ValueError): fromJust(Nothing) self.assertEqual(2, maybe(0, (__ + 1), Just(1))) self.assertEqual(0, maybe(0, (__ + 1)) % Nothing) self.assertEqual(Nothing, listToMaybe(L[[]])) self.assertEqual(Just("a"), listToMaybe(L[["a"]])) self.assertEqual(Just("a"), listToMaybe(L["a", "b"])) self.assertEqual(Just(1), listToMaybe(L[1, ...])) self.assertEqual(L[[]], maybeToList(Nothing)) self.assertEqual(L[[1]], maybeToList(Just(1))) self.assertEqual(L[[]], catMaybes(L[[]])) self.assertEqual(L[[]], catMaybes(L[Nothing, Nothing])) self.assertEqual(L[1, 2], catMaybes(L[Just(1), Just(2)])) self.assertEqual(L[1, 2], catMaybes(L[Just(1), Nothing, Just(2)])) from hask3.Prelude import const self.assertEqual(L[[]], mapMaybe(const(Nothing), L[1, 2])) self.assertEqual(L[1, 2], mapMaybe(Just, L[1, 2])) self.assertEqual(L[[]], mapMaybe(Just, L[[]])) f = (lambda x: Just(x) if x > 3 else Nothing) \ ** (H/ int >> t(Maybe, int)) self.assertEqual(L[4, 5], mapMaybe(f, L[1, ..., 5])) self.assertEqual(L[[]], mapMaybe(f, L[1, ..., 3])) self.assertEqual(1, fromMaybe(1, Nothing)) self.assertEqual(2, fromMaybe(1, Just(2)))
def test_examples(self): @sig(H/ int >> int >> t(Maybe, int)) def safe_div(x, y): return Nothing if y == 0 else Just(x//y) from hask3.Data.Maybe import mapMaybe self.assertEqual(mapMaybe(safe_div(12)) % L[0, 1, 3, 0, 6], L[12, 4, 2]) from hask3.Data.List import isInfixOf self.assertTrue(isInfixOf(L[2, 8], L[1, 4, 6, 2, 8, 3, 7])) from hask3.Control.Monad import join self.assertEqual(join(Just(Just(1))), Just(1)) from hask3.Prelude import flip from hask3.Data.Tuple import snd from hask3.Python.builtins import divmod, hex hexMod = hex * snd * flip(divmod, 16) self.assertEqual(hexMod(24), '0x8')
def test_type_sig(self): tse = TypeSignatureError x = lambda x: x with self.assertRaises(tse): x**(H / int >> 1) with self.assertRaises(tse): x**(H / int >> [int, int]) with self.assertRaises(tse): x**(H / int >> []) with self.assertRaises(tse): x**(H / int >> "AAA") with self.assertRaises(TypeError): t(Maybe, "a", "b") with self.assertRaises(TypeError): t(Either, "a") with self.assertRaises(TypeError): t(Ordering, "a") with self.assertRaises(SyntaxError): sig(sig(H / int >> int)) with self.assertRaises(SyntaxError): sig(H) with self.assertRaises(SyntaxError): H[Eq, "a", "b"] with self.assertRaises(SyntaxError): H[(Eq, Eq)] with self.assertRaises(SyntaxError): H[("a", Eq)] with self.assertRaises(SyntaxError): H[("a", "a")] with self.assertRaises(SyntaxError): H[(Eq, "a", "b")] with self.assertRaises(SyntaxError): H[(Eq, 1)] with self.assertRaises(SyntaxError): H[(Maybe, 1)] with self.assertRaises(SyntaxError): sig(H / "a")(1)
def test_sig(self): @sig(H/ "a" >> "b" >> "a") def const(x, y): return x self.assertEqual(const(1, 2), 1) def const(x, y): return x const = const ** (H/ "a" >> "b" >> "a") self.assertEqual(const(1, 2), 1) f = (lambda x, y: x + y) ** (H/ int >> int >> int) self.assertEqual(5, f(2, 3)) with self.assertRaises(TypeError): f(9, 1.0) g = (lambda a, b, c: a // (b + c)) ** (H/ int >> int >> int >> int) self.assertEqual(g(10, 2, 3), 2) part_g = g(12) self.assertEqual(part_g(2, 2), 3) self.assertEqual(g(20, 1)(4), 4) self.assertEqual(Just * Just * Just * Just % 77, Just(Just(Just(Just(77))))) # add two ints together @sig(H/ int >> int >> int) def add(x, y): return x + y # reverse order of arguments to a function @sig(H/ (H/ "a" >> "b" >> "c") >> "b" >> "a" >> "c") def flip(f, b, a): return f(a, b) # map a Python (untyped) function over a Python (untyped) set @sig(H/ func >> set >> set) def set_map(fn, lst): return set((fn(x) for x in lst)) # map a typed function over a List @sig(H/ (H/ "a" >> "b") >> ["a"] >> ["b"]) def map(f, xs): return L[(f(x) for x in xs)] # type signature with an Eq constraint @sig(H[(Eq, "a")]/ "a" >> ["a"] >> bool) def not_in(y, xs): return not any((x == y for x in xs)) # type signature with a type constructor (Maybe) that has type arguments @sig(H/ int >> int >> t(Maybe, int)) def safe_div(x, y): return Nothing if y == 0 else Just(x//y) # type signature for a function that returns nothing @sig(H/ int >> None) def launch_missiles(num_missiles): return Ratio, R =\ data.Ratio("a") == d.R("a", "a") & deriving(Eq) Rational = t(Ratio, int) @sig(H/ Rational >> Rational >> Rational) def addRational(rat1, rat2): pass from hask3.Prelude import flip h = (lambda x, y: x / y) ** (H/ float >> float >> float) self.assertEqual(h(3.0) * h(6.0) * flip(h, 2.0) % 36.0, 9.0)