Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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))
Exemplo n.º 3
0
    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")), {}, {}))
Exemplo n.º 4
0
    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))
Exemplo n.º 5
0
    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))
Exemplo n.º 6
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)))
Exemplo n.º 7
0
    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')
Exemplo n.º 8
0
    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)
Exemplo n.º 9
0
    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)