示例#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)
示例#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))
示例#3
0
    def test_functions(self):
        from hask3.Prelude import subtract, even, odd, gcd, lcm, id, const, flip
        from hask3.Prelude import until, asTypeOf, error

        self.assertEqual(5, subtract(2, 7))
        self.assertEqual(-5, subtract(7, 2))
        self.assertTrue(even(20) and even(-20))
        self.assertFalse(even(21) and even(-21))
        self.assertTrue(odd(21) and odd(-21))
        self.assertFalse(odd(20) and odd(-20))
        self.assertEqual(4, gcd(8, 12))
        self.assertEqual(4, gcd(8, 12))
        self.assertEqual(2, gcd(-4, 6))
        self.assertEqual(8, gcd(8, 0))
        self.assertEqual(8, gcd(0, 8))
        self.assertEqual(0, gcd(0, 0))
        self.assertEqual(12, lcm(6, 4))
        self.assertEqual(3, lcm(3, 3))
        self.assertEqual(9, lcm(9, 3))
        self.assertEqual(2, lcm(1, 2))
        self.assertEqual(0, lcm(0, 8))
        self.assertEqual(0, lcm(8, 0))
        self.assertEqual(0, lcm(0, 0))

        self.assertEqual("a", id("a"))
        self.assertEqual("a", id * id * id % "a")
        self.assertEqual(1, const(1, 2))
        self.assertEqual(1, const(1) * const(3) % "a")
        self.assertEqual(1, flip(__ - __, 2, 3))
        self.assertEqual(1, flip(const, 2, 1))
        self.assertEqual(2, flip(flip(const))(2, 1))

        self.assertEqual(1, until(__ > 0, __ + 1, -20))
        self.assertEqual(-20, until(__ < 0, __ + 1, -20))
        self.assertEqual("a", asTypeOf("a", "a"))
        self.assertEqual(1, asTypeOf(1, 1))

        # error
        with self.assertRaises(Exception):
            error("")
        msg = "OUT OF CHEESE ERROR"
        try:
            error(msg)
        except Exception as e:
            self.assertEqual((msg, ), e.args)
示例#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))
示例#5
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')
示例#6
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)