Example #1
0
    @classmethod
    def make_instance(self, cls, pure, ap):
        pure = pure**(H[(Applicative, "f")] / "a" >> t("f", "a"))
        ap = ap**(H[(Applicative, "f")] / t("f", H / "a" >> "b") >> t(
            "f", "a") >> t("f", "b"))
        build_instance(Applicative, cls, {"pure": pure, "ap": ap})
        return


@constraint(Applicative(f))
def appAp(fn: f(a >> b), x: f(a)) -> f(b):
    """
    appAp :: Applicative f => f (a -> b) -> f a -> f b
    """
    return Applicative[x].ap(fn, x)


@Infix
def ap(f, x):
    """
    (ap) :: Applicative f => f (a -> b) -> f a -> f b

    This is infix and non-curried version of `appAp`.
    """
    return Applicative[x].ap(f, x)


instance(Applicative,
         List).where(pure=lambda x: L[[x]],
                     ap=lambda fs, xs: L[[f(x) for f in fs for x in xs]])
Example #2
0
    in imperative languages.
    """
    return Monad[m].bind(m, const(k))


@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
    the outer level.
    """
    __id = (lambda x: x)**(H / "a" >> "a")
    return bind(m, __id)


@sig(H[(Monad, "m")] / (H / "a" >> "r") >> t("m", "a") >> t("m", "r"))
def liftM(fn, m):
    """
    liftM :: Monad m => (a1 -> r) -> m a1 -> m r

    Promote a function to a monad.
    """
    return fmap(fn, m)


instance(Monad, List).where(
    bind=lambda x, fn: L[itertools.chain.from_iterable(fmap(fn, x))])
Example #3
0
    The Either type represents values with two possibilities:
    a value of type `Either a b` is either `Left a` or `Right b`.

    The Either type is sometimes used to represent a value which is
    either correct or an error; by convention, the `Left` constructor is used
    to hold an error value and the `Right` constructor is used
    to hold a correct value (mnemonic: “right” also means “correct”).
    """
    Left: a
    Right: b


Left, Right = Either.enums

instance(Functor,
         Either).where(fmap=lambda f, v: ~(caseof(v)
                                           | m(Left(m.e)) >> Left(p.e)
                                           | m(Right(m.ra)) >> Right(f(p.ra))))

instance(Applicative,
         Either).where(pure=Right,
                       ap=lambda v, x: ~(caseof(v)
                                         | m(Left(m.l)) >> Left(p.l)
                                         | m(Right(m.r)) >> fmap(p.r, x)))

instance(Monad, Either).where(bind=lambda v, f: ~(caseof(v)
                                                  | m(Left(m.e)) >> Left(p.e)
                                                  | m(Right(m.a)) >> f(p.a)))


def in_either(fn):
    """
Example #4
0
    return not elem(x, t)


@constraint(Foldable(r))
def find(f: a >> bool, t: r(a)) -> Maybe(a):
    """
    find :: Foldable r => (a -> bool) -> r a -> Maybe a

    The find function takes a predicate and a structure and returns the
    leftmost element of the structure matching the predicate, or Nothing if
    there is no such element.
    """
    return DL.find(f, toList(t))


#=============================================================================#
# Instances

instance(Foldable, List).where(foldr=DL.foldr,
                               foldr1=DL.foldr1,
                               foldl=DL.foldl,
                               foldl_=DL.foldl_,
                               foldl1=DL.foldl1,
                               null=DL.null,
                               length=DL.length,
                               elem=DL.elem,
                               minimum=DL.minimum,
                               maximum=DL.maximum,
                               sum=DL.sum,
                               product=DL.product)
Example #5
0

@sig(H[(Num, "a")] / "a" >> "a" >> "a")
def mul(a, b):
    """
    mul :: Num a => a -> a -> a

    Multiplies two numbers.
    """
    return Num[a].mul(a, b)


instance(Num, int).where(add=int.__add__,
                         mul=int.__mul__,
                         abs=int.__abs__,
                         signum=lambda x: -1 if x < 0 else (1 if x > 0 else 0),
                         fromInteger=int,
                         negate=int.__neg__,
                         sub=int.__sub__)

instance(Num, float).where(add=float.__add__,
                           mul=float.__mul__,
                           abs=float.__abs__,
                           signum=lambda x: -1.0
                           if x < 0.0 else (1.0 if x > 0.0 else 0.0),
                           fromInteger=float,
                           negate=float.__neg__,
                           sub=float.__sub__)

instance(Num, complex).where(add=complex.__add__,
                             mul=complex.__mul__,
Example #6
0
@annotated
def unsafePerformIO(io: IO(a)) -> a:
    """
    unsafePerformIO :: IO a -> a

    Unsafe performs IO.
    """
    return io.i0(Star)


@annotated
def unsafeFmapIO(f: a >> b, x: IO(a), n: Unit) -> b:
    return f(unsafePerformIO(x))


@annotated
def unsafeApIO(fn: IO(a >> b), x: IO(a), n: Unit) -> b:
    return unsafePerformIO(fn)(unsafePerformIO(x))


@annotated
def unsafeBindIO(x: IO(a), f: a >> IO(b), n: Unit) -> b:
    return unsafePerformIO(f(unsafePerformIO(x)))


instance(Functor, IO).where(fmap=lambda f, x: LazyPure(unsafeFmapIO(f, x)))
instance(Applicative, IO).where(pure=pure,
                                ap=lambda f, x: LazyPure(unsafeApIO(f, x)))
instance(Monad, IO).where(bind=lambda x, f: LazyPure(unsafeBindIO(x, f)))
Example #7
0
@Infix
def map(f, x):
    """
    (map) :: Functor f => (a -> b) -> (f a -> f b)

    This is infix and non-curried version of `fmap`.
    Maps function over functor.
    """
    return Functor[x].fmap(f, x)


@constraint(Functor(f))
def fmap(fn: a >> b, x: f(a)) -> f(b):
    """
    fmap :: Functor f => (a -> b) -> (f a -> f b)

    Maps function over functor.
    """
    return Functor[x].fmap(fn, x)


@constraint(Functor(f))
def void(x: f(a)) -> f(Unit):
    return fmap(const(Star), x)


instance(
    Functor,
    List).where(fmap=lambda fn, lst: L[builtins.map(fn, builtins.iter(lst))])

instance(Functor, TypedFunc).where(fmap=TypedFunc.__mul__)
Example #8
0
    (represented as ``Just a``), or it is empty (represented as ``Nothing``).
    Using Maybe is a good way to deal with errors or exceptional cases
    without resorting to drastic measures such as error.

    The ``Maybe`` type is also a monad.
    It is a simple kind of error monad,
    where all errors are represented by ``Nothing``.
    A richer error monad can be built using the ``Either`` type.
    """
    Nothing : []
    Just : a
Nothing, Just = Maybe.enums

instance(Functor, Maybe).where(
    fmap = lambda f, x: ~(caseof(x)
                            | m(Just(m.a)) >> Just(f(p.a))
                            | m(Nothing)   >> Nothing)
)

instance(Applicative, Maybe).where(
    pure = Just,
    ap = lambda fs, xs: ~(caseof((fs, xs))
                            | m((Just(m.f), Just(m.x))) >> Just(p.f(p.x))
                            | m((Nothing, m.x)) >> Nothing)
)

instance(Monad, Maybe).where(
    bind = lambda x, f: ~(caseof(x)
                            | m(Just(m.a)) >> f(p.a)
                            | m(Nothing)   >> Nothing)
)