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})
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)])')
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)
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)
""" @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
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.
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)``
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]``
def make_instance(cls, instance, children): children = children ** (H/ 'a' >> t('f', 'b')) build_instance(cls, instance, {'children': lambda self: children(self)})
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
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``
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):
- ``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)
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