/* * Copyright 2021 Felix Wiemuth * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */////// Trait for types that support monadic bind (`flatMap`), and its functions.///pubmod Monad {////// Trait for types that support monadic bind (`flatMap`).////// A monad is an applicative that allows to apply a function that takes a normal value and/// produces a monadic value to a monadic value. That is, the bind mechanism/// supports extraction of monadic values, or, viewed differently, allows to combine (flatten) nested/// monadic values (`flapMap` can be understood as a `Functor.map` followed by a `flatten`).///pubtraitMonad[m: Type -> Type] withApplicative[m] {////// Apply function `f` to the monadic value `x`, resulting in a combined monadic value.///pubdefflatMap(f: a -> m[b] \ ef, x: m[a]): m[b] \ ef }////// The monadic `join` operator./// Flatten `x` - a monadic action nested in an outer monadic layer - to a single layer.////// E.g. for the Option monad: `flatten(Some(Some(1)))` becomes `Some(1)`.///pubdefflatten(x: m[m[a]]): m[a] withMonad[m] = flatMap(identity, x)////// The left-to-right Kleisli composition operator for monads.////// Map `x` with the monadic function `f1` and then map its result with the function `f2`.///pubdefkleisliLeft(f1: a -> m[b] \ ef1, f2: b -> m[c] \ ef2, x: a): m[c] \ { ef1, ef2 } withMonad[m] =flatMap(x1 -> f2(x1), f1(x))////// The right-to-left Kleisli composition operator for monads.////// Map `x` with the monadic function `f2` and then map its result with the function `f1`.///pubdefkleisliRight(f1: b -> m[c] \ ef1, f2: a -> m[b] \ ef2, x: a): m[c] \ { ef1, ef2 } withMonad[m] =flatMap(x1 -> f1(x1), f2(x))////// `=<<` is an operator alias for `flatMap`.///pubdef=<<(k: a -> m[b] \ ef, x: m[a]): m[b] \ efwithMonad[m] = flatMap(k, x)////// `>>=` is the operator `=<<` with its arguments flipped.////// `>>=` is the monadic bind operator.///pubdef>>=(x: m[a], k: a -> m[b] \ ef): m[b] \ efwithMonad[m] = flatMap(k, x)////// `>=>` is an operator alias for `kleisliLeft`.///pubdef>=>(f1: a -> m[b] \ ef1, f2: b -> m[c] \ ef2): a -> m[c] \ { ef1, ef2 } withMonad[m] = x ->kleisliLeft(f1, f2, x)////// `<=<` is an operator alias for `kleisliRight`.///pubdef<=<(f1: b -> m[c] \ ef1, f2: a -> m[b] \ ef2): a -> m[c] \ { ef1, ef2 } withMonad[m] = x ->kleisliRight(f1, f2, x)}