def test_match(self): @sig(H/ int >> int) def fib(x): return ~(caseof(x) | m(0) >> 1 | m(1) >> 1 | m(m.n) >> fib(p.n - 2) + fib(p.n - 1) ) self.assertEqual(1, fib(0)) self.assertEqual(1, fib(1)) self.assertEqual(13, fib(6)) def default_to_zero(x): return ~(caseof(x) | m(Just(m.x)) >> p.x | m(Nothing) >> 0) self.assertEqual(default_to_zero(Just(27)), 27) self.assertEqual(default_to_zero(Nothing), 0) self.assertEqual(Just(20.0)[0], 20.0) self.assertEqual(Left("words words words words")[0], "words words words words") with self.assertRaises(IndexError): Nothing[0]
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 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_show(self): from hask3.Prelude import show self.assertEqual("Just(3)", str(Just(3))) self.assertEqual("Just(3)", show(Just(3))) self.assertEqual("Just('a')", str(Just("a"))) self.assertEqual("Just('a')", show(Just("a"))) self.assertEqual("Just(Just(3))", str(Just(Just(3)))) self.assertEqual("Just(Just(3))", show(Just(Just(3)))) self.assertEqual("Nothing", str(Nothing)) self.assertEqual("Nothing", show(Nothing))
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_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_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_decorators(self): def eat_cheese(cheese): if cheese <= 0: raise ValueError("Out of cheese error") return cheese - 1 maybe_eat = in_maybe(eat_cheese) self.assertEqual(maybe_eat(1), Just(0)) self.assertEqual(maybe_eat(0), Nothing) self.assertEqual(Just(6), Just(7) >> maybe_eat) self.assertEqual(Just(7), Just(10) >> maybe_eat >> maybe_eat >> maybe_eat) self.assertEqual(Nothing, Just(1) >> maybe_eat >> maybe_eat >> maybe_eat) either_eat = in_either(eat_cheese) self.assertEqual(either_eat(10), Right(9)) self.assertTrue(isinstance(either_eat(0)[0], ValueError))
def safe_div(x, y): return Nothing if y == 0 else Just(x//y)
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 safediv(x, y): return Just(x // y) if y != 0 else Nothing
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_functor(self): from hask3.Prelude import id, fmap plus1 = (lambda x: x + 1)**(H / int >> int) toStr = str**(H / int >> str) self.assertEqual(Just(Just(2)), fmap(Just, Just(2))) self.assertEqual(Just(3), plus1 * Just(2)) self.assertEqual(Just("1"), toStr * Just(1)) self.assertEqual(Just("3"), (toStr * plus1) * Just(2)) # functor laws self.assertEqual(fmap(id, Just(4)), Just(4)) self.assertEqual(fmap(id, Nothing), Nothing) self.assertEqual(id * Just(4), Just(4)) self.assertEqual(id * Nothing, Nothing) self.assertEqual(fmap(toStr, fmap(plus1, Just(2))), fmap(toStr * plus1, Just(2))) self.assertEqual((toStr * (plus1 * Just(2))), (toStr * plus1) * Just(2))
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)
def default_to_zero(x): return ~(caseof(x) | m(Just(m.x)) >> p.x | m(Nothing) >> 0)
def test_match(self): match_only = lambda v, p: pattern_match(v, p)[0] pb = PatternMatchBind # literal matches self.assertTrue(match_only(1, 1)) self.assertTrue(match_only((1, "a"), (1, "a"))) self.assertTrue(match_only(Nothing, Nothing)) self.assertTrue(match_only(Just(1), Just(1))) self.assertFalse(match_only(2, 1)) self.assertFalse(match_only(("a", 1), (1, "a"))) self.assertFalse(match_only(("a", "b"), ["a", "b"])) self.assertFalse(match_only(Nothing, Just(Nothing))) self.assertFalse(match_only(Just(2), Just(1))) self.assertFalse(match_only(Right(2), Just(2))) self.assertFalse(match_only(Right(2), Left(2))) # matches with wildcard (i.e, discarded variable bind) self.assertTrue(match_only(1, pb("_"))) self.assertTrue(match_only(Nothing, pb("_"))) self.assertTrue(match_only(Just("whatever"), Just(pb("_")))) self.assertTrue(match_only(Right(Just(5)), Right(Just(pb("_"))))) self.assertTrue(match_only(("a", "b", "c"), ("a", pb("_"), "c"))) self.assertFalse(match_only(("a", "b", "c"), ("1", pb("_"), "c"))) self.assertFalse(match_only(("a", "b", "d"), ("a", pb("_"), "c"))) # matches with variable binding self.assertEqual((True, {"a": 1}), pattern_match(1, pb("a"))) self.assertEqual((True, { "a": 1, "b": 2 }), pattern_match((1, 2), (pb("a"), pb("b")))) self.assertEqual((True, { "a": 8 }), pattern_match(Just(8), Just(pb("a")))) self.assertEqual((True, { "a": "a" }), pattern_match(Right(Just("a")), Right(Just(pb("a"))))) self.assertEqual((False, { "a": 1 }), pattern_match((2, 1), (3, pb("a")))) self.assertEqual((True, { "a": 1, "b": 2, "_": "a" }), pattern_match((1, "a", 2), (pb("a"), pb("_"), pb("b")))) with self.assertRaises(SyntaxError): pattern_match((1, 2), (pb("c"), pb("a")), {"c": 1}) with self.assertRaises(SyntaxError): pattern_match((1, 2), (pb("c"), pb("a")), {"a": 1})
def test_eq(self): self.assertEqual(Nothing, Nothing) self.assertEqual(Just(3), Just(3)) self.assertEqual(Just("3"), Just("3")) self.assertNotEqual(Just(1), Just(3)) self.assertNotEqual(Just(3), Nothing) self.assertNotEqual(Nothing, Just(0)) self.assertTrue(Just(1) == Just(1)) self.assertFalse(Just(1) == Just(2)) self.assertTrue(Nothing == Nothing or Nothing != Nothing) self.assertTrue(Just(1) == Just(1) or Just(1) != Just(1)) self.assertFalse(Nothing == Nothing and Nothing != Nothing) self.assertFalse(Just(1) == Just(1) and Just(1) != Just(1)) with self.assertRaises(TypeError): Just(1) == Just("1") with self.assertRaises(TypeError): Just(1) == Just(1.0) with self.assertRaises(TypeError): Nothing == None # noqa with self.assertRaises(TypeError): Nothing == 1 with self.assertRaises(TypeError): Just(1) == 1
def test_ord(self): self.assertTrue(Nothing < Just(0)) self.assertTrue(Nothing < Just("a")) self.assertTrue(Nothing < Just(-float("inf"))) self.assertTrue(Nothing <= Just(0)) self.assertTrue(Nothing <= Just("a")) self.assertTrue(Nothing <= Just(-float("inf"))) self.assertTrue(Nothing >= Nothing and Nothing <= Nothing) self.assertFalse(Nothing > Just(0)) self.assertFalse(Nothing > Just("a")) self.assertFalse(Nothing > Just(-float("inf"))) self.assertFalse(Nothing >= Just(0)) self.assertFalse(Nothing >= Just("a")) self.assertFalse(Nothing >= Just(-float("inf"))) self.assertFalse(Nothing > Nothing or Nothing < Nothing) self.assertTrue(Just(1) > Just(0)) self.assertTrue(Just(Just(1)) > Just(Nothing)) self.assertTrue(Just(Just(Nothing)) > Just(Nothing)) self.assertTrue(Just(1) >= Just(0)) self.assertTrue(Just(1) >= Just(1)) self.assertTrue(Just(Just(1)) >= Just(Nothing)) self.assertTrue(Just(Just(Nothing)) >= Just(Nothing)) self.assertTrue(Just(Just(Nothing)) >= Just(Just(Nothing))) self.assertFalse(Just(0) > Just(1)) self.assertFalse(Just(0) > Just(0)) self.assertFalse(Just(Nothing) > Just(Just(1))) self.assertFalse(Just(Nothing) > Just(Just(Nothing))) self.assertFalse(Just(0) >= Just(1)) self.assertFalse(Just(Nothing) >= Just(Just(1))) self.assertFalse(Just(Nothing) >= Just(Just(Nothing))) self.assertTrue(Just(0) < Just(1)) self.assertTrue(Just(Nothing) < Just(Just(1))) self.assertTrue(Just(Nothing) < Just(Just(Nothing))) self.assertTrue(Just(0) <= Just(1)) self.assertTrue(Just(Nothing) <= Just(Just(1))) self.assertTrue(Just(Nothing) <= Just(Just(Nothing))) self.assertFalse(Just(1) < Just(0)) self.assertFalse(Just(1) < Just(1)) self.assertFalse(Just(Just(1)) < Just(Nothing)) self.assertFalse(Just(Just(Nothing)) < Just(Nothing)) self.assertFalse(Just(1) <= Just(0)) self.assertTrue(Just(1) <= Just(1)) self.assertFalse(Just(Just(1)) <= Just(Nothing)) self.assertFalse(Just(Just(Nothing)) <= Just(Nothing)) self.assertTrue(Just(Just(Nothing)) <= Just(Just(Nothing))) with self.assertRaises(TypeError): Just(1) > Just(1.0) with self.assertRaises(TypeError): Just(1) >= Just(1.0) with self.assertRaises(TypeError): Just(1) < Just(1.0) with self.assertRaises(TypeError): Just(1) <= Just(1.0) with self.assertRaises(TypeError): Just(1) > Just(Just(1)) with self.assertRaises(TypeError): Just(1) >= Just(Just(1)) with self.assertRaises(TypeError): Just(1) < Just(Just(1)) with self.assertRaises(TypeError): Just(1) <= Just(Just(1))
def test_caseof(self): # literal matching self.assertEqual(1, ~(caseof("a") | m("a") >> 1)) self.assertEqual( 1, ~(caseof(2.0) | m(2.0) >> ~(caseof("a") | m("b") >> 3 | m("a") >> 1) | m(2.0) >> 2)) self.assertEqual( "x", ~(caseof(Just("x")) | m(Nothing) >> False | m(Just("x")) >> "x")) self.assertEqual(1, ~(caseof([1, 2]) | m((1, 2)) >> 2 | m([1, 2]) >> 1)) self.assertEqual( True, ~(caseof(GT) | m(LT) >> False | m(EQ) >> False | m(GT) >> True)) self.assertEqual( 2, ~(caseof((1, 2, 3)) | m((1, 2)) >> 1 | m((1, 2, 3)) >> 2)) with self.assertRaises(IncompletePatternError): ~(caseof(1) | m(2) >> 2) # matches with wildcard self.assertEqual(1, ~(caseof(1) | m(m._) >> 1 | m(1) >> 2)) self.assertEqual( True, ~(caseof(GT) | m(LT) >> False | m(EQ) >> False | m(m._) >> True)) self.assertEqual( False, ~(caseof(GT) | m(LT) >> False | m(m._) >> False | m(GT) >> True)) self.assertEqual( 2, ~(caseof((1, 2, 3)) | m((2, 1, 3)) >> 1 | m((1, m._, 3)) >> 2 | m((1, 2, 3)) >> 3)) # variable bind self.assertEqual(("b", "a"), ~(caseof(("a", "b")) | m((m.x, m.y)) >> (p.y, p.x) | m(m._) >> None)) self.assertEqual( 1, ~(caseof(Just(1)) | m(Just(m.x)) >> p.x | m(Nothing) >> 0)) self.assertEqual( Just(0), ~(caseof(Nothing) | m(Just(m.x)) >> Just(p.x + 1) | m(Nothing) >> Just(0))) self.assertEqual(1, ~(caseof(2) | m((m.a, m.a)) >> p.a | m(2) >> 1)) self.assertEqual( 1, ~(caseof(Just(10)) | m(Just(m.a)) >> ~(caseof(1) | m(m.a) >> p.a | m(m._) >> False) | m(Nothing) >> 11)) # cons matches self.assertEqual([3], ~(caseof([1, 2, 3]) | m(1 ^ (2 ^ m.x)) >> p.x | m(m.x) >> False)) self.assertEqual([3, 2, 1], ~(caseof([3, 2, 1]) | m(m.a ^ (2 ^ m.c)) >> [p.a, 2, p.c[0]] | m(m.x) >> False)) self.assertEqual([3, 2, [1, 0]], ~(caseof([3, 2, 1, 0]) | m(m.a ^ (m.b ^ m.c)) >> [p.a, p.b, p.c] | m(m.x) >> False)) self.assertEqual( L[3, 2, 1], ~(caseof(L[3, 2, 1, 0]) | m(m.a ^ (m.b ^ m.c)) >> L[p.a, p.b, p.c[0]] | m(m.x) >> False)) self.assertEqual( 1, ~(caseof(L[1, ...]) | m(m.a ^ m.b) >> p.a | m(m.a) >> False)) self.assertTrue(~(caseof(L[[]]) | m(m.a ^ m.b) >> False | m(m.a) >> True)) with self.assertRaises(SyntaxError): ~(caseof((1, 2)) | m((m.a, m.a)) >> p.a | m(1) >> 1) with self.assertRaises(SyntaxError): ~(caseof([1, 2, 3, 4]) | m(m.a ^ m.b ^ m.c) >> True | m(m.x) >> False) with self.assertRaises(SyntaxError): ~(caseof(L[1, 2, 2]) | m(m.a ^ 1) >> False | m(m.a) >> True)