//@NO-IMPLICIT-PRELUDE
//! Conveniences for working with functions.
let { Semigroup } = import! std.semigroup
let { Monoid } = import! std.monoid
let { Category } = import! std.category
let { Functor } = import! std.functor
let { Monad } = import! std.monad
let { Applicative } = import! std.applicative
let semigroup s : Semigroup b -> Semigroup (a -> b) = {
append = \f g x -> s.append (f x) (g x) }
let monoid m : Monoid b -> Monoid (a -> b) = {
semigroup = semigroup m.semigroup,
empty = \_ -> m.empty,
}
let category : Category (->) = {
id = \x -> x,
compose = \f g x -> f (g x),
}
let functor : Functor ((->) a) = { map = category.compose }
let applicative : Applicative ((->) a) = {
functor = functor,
apply = \f g x -> f x (g x),
wrap = \x y -> x,
}
let monad : Monad ((->) a) = {
applicative = applicative,
flat_map = \f m x -> f (m x) x,
}
/// The identity function, where `id x == x`
let id : a -> a = category.id
/// const `x` creates a function that always returns `x`
let const : a -> b -> a = applicative.wrap
/// flip `f` creates a new function that takes its two arguments in reverse order
let flip f x y : (a -> b -> c) -> b -> a -> c = f y x
/// Backward function application, where `f <| x == f x`
#[infix(right, 0)]
let (<|) f x : (a -> b) -> a -> b = f x
/// Forward function application, where `x |> f == f x`
#[infix(left, 0)]
let (|>) x f : a -> (a -> b) -> b = f x
/// Right-to-left function composition
#[infix(right, 9)]
let (<<) : (b -> c) -> (a -> b) -> a -> c = category.compose
/// Left-to-right function composition
#[infix(left, 9)]
let (>>) : (a -> b) -> (b -> c) -> a -> c = flip category.compose
{
semigroup,
monoid,
category,
functor,
applicative,
monad,
id,
const,
flip,
(<|),
(|>),
(<<),
(>>),
}