Пример #1
0
 def make_instance(typeclass, cls, bind):
     from hask3.hack import is_builtin
     from hask3.lang.type_system import build_instance
     from hask3.lang.syntax import H, t
     bind = bind ** (H[Monad, "m"]/
                     t("m", "a") >> (H/ "a" >> t("m", "b")) >> t("m", "b"))
     if not is_builtin(cls):
         def bind_wrap(s, o):
             return Monad[s].bind(s, o)
         cls.__rshift__ = bind_wrap
     build_instance(Monad, cls, {"bind": bind})
Пример #2
0
    def test_typeclasses_x(self):
        # Instantiate using defined higher-kinded type
        instance(Composite, t(t(Tree, 'a'), Maybe, [t(Tree, 'a')])).where(
            children=tree_children
        )

        # String representation for higher-kinded type.
        self.assertEqual(str(t(t(Tree, 'a'), Maybe, [t(Tree, 'a')])),
                         '((Tree a) Maybe [(Tree a)])')
Пример #3
0
def in_either(fn):
    """Decorator for monadic error handling.

    If the decorated function raises an exception, return the exception inside
    `Left`.  Otherwise, take the result and wrap it in `Right`.

    """
    from hask3.lang.syntax import typify, t

    def closure_in_either(*args, **kwargs):
        try:
            return Right(fn(*args, **kwargs))
        except Exception as e:
            return Left(e)

    return typify(fn, hkt=lambda x: t(Either, "aa", x))(closure_in_either)
Пример #4
0
def in_maybe(fn):
    """Decorator for monadic error handling.

    If the decorated function raises an exception, return `Nothing`.
    Otherwise, take the result and wrap it in a `Just`.

    """
    from hask3.lang.syntax import typify, t

    def closure_in_maybe(*args, **kwargs):
        try:
            return Just(fn(*args, **kwargs))
        except:  # noqa
            return Nothing

    return typify(fn, hkt=lambda x: t(Maybe, x))(closure_in_maybe)
Пример #5
0
    """
    @classmethod
    def make_instance(typeclass, cls, bind):
        from hask3.hack import is_builtin
        from hask3.lang.type_system import build_instance
        from hask3.lang.syntax import H, t
        bind = bind ** (H[Monad, "m"]/
                        t("m", "a") >> (H/ "a" >> t("m", "b")) >> t("m", "b"))
        if not is_builtin(cls):
            def bind_wrap(s, o):
                return Monad[s].bind(s, o)
            cls.__rshift__ = bind_wrap
        build_instance(Monad, cls, {"bind": bind})


@sig(H[Monad, "m"]/ t("m", "a") >> (H/ "a" >> t("m", "b")) >> t("m", "b"))
def bind(m, fn):
    """``bind :: Monad m => m a -> (a -> m b) -> m b``

    Monadic bind.

    """
    return Monad[m].bind(m, fn)


@sig(H[Monad, "m"]/ t("m", t("m", "a")) >> t("m", "a"))
def join(m):
    """``join :: Monad m => m (m a) -> m a``

    The join function is the conventional monad join operator.  It is used to
    remove one level of monadic structure, projecting its bound argument into
Пример #6
0
        p = (lambda x: DL.product(toList(x))) if product is None else product

        attrs = {"foldr": foldr, "foldr1": foldr1, "foldl": foldl,
                 "foldl_": foldl_, "foldl1": foldl1, "toList": toList,
                 "null": null, "length": length, "elem": elem, "maximum": ma,
                 "minimum": mi, "sum": sum, "product": p}
        build_instance(Foldable, cls, attrs)

        if not hasattr(cls, "__len__") and not is_builtin(cls):
            cls.__len__ = length

        if not hasattr(cls, "__iter__") and not is_builtin(cls):
            cls.__iter__ = lambda x: iter(toList(x))


@sig(H[(Foldable, "t")]/ (H/ "a" >> "b" >> "b") >> "b" >> t("t", "a") >> "b")
def foldr(f, z, t):
    """``foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b``

    Right-associative fold of a structure.

    """
    return Foldable[t].foldr(f, z, t)


@sig(H[(Foldable, "t")]/ (H/ "a" >> "a" >> "a") >> t("t", "a") >> "a")
def foldr1(f, t):
    """``foldr1 :: Foldable t => (a -> a -> a) -> t a -> a``

    A variant of foldr that has no base case, and thus may only be applied to
    non-empty structures.
Пример #7
0
    Minimal complete definition:

    - ``traverse``

    """
    @classmethod
    def make_instance(typeclass, cls, traverse, sequenceA=None, mapM=None,
                      sequence=None):
        from hask3.lang.type_system import build_instance
        attrs = {"traverse": traverse, "sequenceA": sequenceA, "mapM": mapM,
                 "sequence": sequence}
        build_instance(Traversable, cls, attrs)


@sig(H[(Applicative, "f"), (Traversable, "t")]/
        (H/ "a" >> t("f", "b")) >> t("t", "a") >> t("f", t("t", "b")))
def traverse(f, t):
    """``traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)``

    Map each element of a structure to an action, evaluate these these actions
    from left to right, and collect the results.  For a version that ignores
    the results see `traverse_`:func:.

    """
    return Traversable[t].traverse(f, t)


@sig(H[(Applicative, "f"), (Traversable, "t")]/
        t("t", t("f", "a")) >> t("f", t("t", "a")))
def sequenceA(t):
    """``sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)``
Пример #8
0
    If the decorated function raises an exception, return the exception inside
    `Left`.  Otherwise, take the result and wrap it in `Right`.

    """
    from hask3.lang.syntax import typify, t

    def closure_in_either(*args, **kwargs):
        try:
            return Right(fn(*args, **kwargs))
        except Exception as e:
            return Left(e)

    return typify(fn, hkt=lambda x: t(Either, "aa", x))(closure_in_either)


@sig(H / (H / "a" >> "c") >> (H / "b" >> "c") >> t(Either, "a", "b") >> "c")
def either(fa, fb, e):
    """``either :: (a -> c) -> (b -> c) -> Either a b -> c``

    Case analysis for the Either type.  If the value is Left(a), apply the
    first function to a; if it is Right(b), apply the second function to b.

    """
    from hask3.lang.syntax import caseof, m, p
    return ~(caseof(e) | m(Left(m.a)) >> fa(p.a) | m(Right(m.b)) >> fb(p.b))


@sig(H / [t(Either, "a", "b")] >> ["a"])
def lefts(xs):
    """``lefts :: [Either a b] -> [a]``
Пример #9
0
 def make_instance(cls, instance, children):
     children = children ** (H/ 'a' >> t('f', 'b'))
     build_instance(cls, instance,
                    {'children': lambda self: children(self)})
Пример #10
0
    container of type `f`.

    Attributes:

    - ``children :: a -> f b``

    '''
    @classmethod
    def make_instance(cls, instance, children):
        children = children ** (H/ 'a' >> t('f', 'b'))
        build_instance(cls, instance,
                       {'children': lambda self: children(self)})


Tree, Leaf, Node = data.Tree('a') == (
    d.Leaf | d.Node('a', [t(data.Tree, 'a')]) &
    deriving(Show, Eq)
)


def tree_children(t):
    return ~(caseof(t)
             | m(Leaf) >> Nothing
             | m(Node(m.p, m.xs)) >> Just(p.xs))


class TestTypeclassX(unittest.TestCase):
    def test_typeclasses_x(self):
        # Instantiate using defined higher-kinded type
        instance(Composite, t(t(Tree, 'a'), Maybe, [t(Tree, 'a')])).where(
            children=tree_children
Пример #11
0
from hask3.lang.syntax import t

# Current implementation is just a wrapper around Python's Fraction.  This is
# not a long-term solution (not extensible beyond builtin types) but it will
# do for now.

from hask3.Data.Num import Ratio
from hask3.Data.Num import R  # noqa
from hask3.Data.Num import toRational  # noqa

from hask3.Data.Num import Integral
from hask3.Data.Num import RealFrac
from hask3.Data.Num import Rational


@sig(H[(Integral, "a")] / t(Ratio, "a") >> "a")
def numerator(ratio):
    """``numerator :: Integral a => Ratio a -> a``

    Extract the numerator of the ratio in reduced form: the numerator and
    denominator have no common factor and the denominator is positive.

    """
    from hask3.Data.Num import toRatio
    return toRatio(ratio[0], ratio[1])[0]


@sig(H[(Integral, "a")] / t(Ratio, "a") >> "a")
def denominator(ratio):
    """``denominator :: Integral a => Ratio a -> a``
Пример #12
0
    If the decorated function raises an exception, return `Nothing`.
    Otherwise, take the result and wrap it in a `Just`.

    """
    from hask3.lang.syntax import typify, t

    def closure_in_maybe(*args, **kwargs):
        try:
            return Just(fn(*args, **kwargs))
        except:  # noqa
            return Nothing

    return typify(fn, hkt=lambda x: t(Maybe, x))(closure_in_maybe)


@sig(H / "b" >> (H / "a" >> "b") >> t(Maybe, "a") >> "b")
def maybe(default, f, maybe_a):
    """Apply `f` to `maybe_a` (if possible) or return `default`.

    Take a `default` value, a function, and a Maybe value.  If the Maybe value
    is Nothing, return the default value.  Otherwise, apply the function to
    the value inside the Just and return the result.

    Type signature: ``maybe :: b -> (a -> b) -> Maybe a -> b``.

    """
    return default if maybe_a == Nothing else f(maybe_a[0])


@sig(H / t(Maybe, "a") >> bool)
def isJust(a):
Пример #13
0
    - ``fromRational``
    - ``div``

    """
    @classmethod
    def make_instance(typeclass, cls, fromRational, div, recip=None):
        from hask3.lang.type_system import build_instance
        if recip is None:
            recip = lambda x: div(1, x)
        attrs = {"fromRational": fromRational, "div": div, "recip": recip}
        build_instance(Fractional, cls, attrs)


Ratio, R = (data.Ratio("a") == d.R("a", "a") & deriving(Eq))

Rational = t(Ratio, int)

instance(Fractional,
         float).where(fromRational=lambda rat: float(rat[0]) / float(rat[1]),
                      div=lambda a, b: float(a) / float(b),
                      recip=lambda x: 1.0 / x)


@sig(H[(Fractional, "a")] / "a" >> "a")
def recip(a):
    """``recip :: Fractional a => a -> a``

    Reciprocal fraction.

    """
    return Fractional[a].recip(a)
Пример #14
0
def lcm(x, y):
    """``lcm :: Integral a => a -> a -> a``

    The smallest positive integer that both `x` and `y` divide.

    """
    g = gcd(x, y)
    return 0 if g == 0 else (x * y) // g


from hask3.Data.Functor import Functor
from hask3.Control.Applicative import Applicative
from hask3.Control.Monad import Monad


@sig(H[(Monad, "m")] / t("m", "a") >> t("m", None))
def sequence(xs):
    """``sequence :: Monad m => [m a] -> m [a]``

    Evaluate each action in the sequence from left to right, and collect the
    results.

    """
    raise NotImplementedError()


@sig(H[(Monad, "m")] / t("m", "a") >> t("m", None))
def sequence_(xs):
    """``sequence_ :: Monad m => [m a] -> m None``

    Evaluate each action in the sequence from left to right, and ignore the