The Lynx programming language
Simplicity, consistency, flexibility - and being intuitive.
Example:
trait Functor (F: Type -> Type) {
fmap: @~(A, B) -> (A -> B) -> F A -> F B
}
trait Applicative (F: Type -> Type) {
pure: @~A -> A -> F A;
apply: @~(A, B) -> F (A->B) -> F A -> F B
}
trait Monad (M: Type -> Type) {
return: @~A -> A -> M A;
bind: @~(A, B) -> M A -> (A -> M B) -> M B
}
impl Functor F for (F, a: Applicative F) {
fmap = a.apply * a.pure
}
impl Applicative M for (M, m: Monad M) {
pure = m.return;
fn apply mf ma {
m.bind mf (f =>
m.bind ma (a =>
m.return (f a)))
}
}