Skip to content

Instantly share code, notes, and snippets.

@ClarkeRemy
Created February 1, 2025 11:50
Show Gist options
  • Save ClarkeRemy/79c3246173ccbf09b544e4f381715d20 to your computer and use it in GitHub Desktop.
Save ClarkeRemy/79c3246173ccbf09b544e4f381715d20 to your computer and use it in GitHub Desktop.
small revisiting Cats in Rust
use core::ops::ControlFlow;
use std::{marker::PhantomData, sync::Arc};
// HKT
#[allow(non_camel_case_types)]
pub type a_<'a, F, T> = <F as A_Funct>::F<'a, T>;
#[allow(non_camel_case_types)]
pub trait A_Funct { type F<'a, T>; }
pub type __<F, T> = <F as Funct>::F<T>;
pub trait Funct { type F<T>; }
// FUNCTOR
#[allow(non_camel_case_types)] pub trait A_Functor <F : A_Funct = Self> { fn a_map<'a,A,B>( fa : &a_<'a,F,A>, f : impl Fn(&A)->B + 'a )-> a_<'a,F,B>; }
#[allow(non_camel_case_types)] pub trait A_FunctorOnce<F : A_Funct = Self> { fn a_map<'a,A,B>( fa : a_<'a,F,A>, f : impl FnOnce(A)->B + 'a )-> a_<'a,F,B>; }
pub trait Functor <F : Funct = Self> { fn map<A,B>( fa : &__<F,A>, f : impl Fn(A)->B )-> __<F,B>; }
pub trait FunctorOnce<F : Funct = Self> { fn map<A,B>( fa : __<F,A>, f : impl FnOnce(A)->B )-> __<F,B>; }
// INVARIANT
#[allow(non_camel_case_types)] pub trait A_Invariant <F : A_Funct = Self> { fn a_imap <'a,A,B>( fa : &a_<'a,F, A>, f : impl Fn(&A)->B, g : impl Fn(&B)->A ) -> a_<'a,F,B>; }
#[allow(non_camel_case_types)] pub trait A_InvariantOnce<F : A_Funct = Self> { fn a_imap_once<'a,A,B>( fa : a_<'a,F, A>, f : impl FnOnce(A)->B, g : impl FnOnce(B)->A) -> a_<'a,F,B>; }
pub trait Invariant <F : Funct = Self> { fn imap <A,B>( fa : &__<F, A>, f : impl Fn(&A)->B, g : impl Fn(&B)->A ) -> __<F,B>; }
pub trait InvariantOnce<F : Funct = Self> { fn imap_once<A,B>( fa : __<F, A>, f : impl FnOnce(A)->B, g : impl FnOnce(B)->A) -> __<F,B>; }
// F_UNIT
#[allow(non_camel_case_types)] pub trait A_FUnit<F : A_Funct = Self> { fn unit<'a>()-> a_<'a,F,()>; }
pub trait FUnit<F : Funct = Self> { fn unit()-> __<F,()>; }
// SEMIGROUPAL
#[allow(non_camel_case_types)] pub trait A_Semigroupal <F : A_Funct = Self> { fn a_product <'a,A,B>(fa : &a_<'a,F,A>, fb : &a_<'a,F,B>) -> a_<'a,F,(A,B)> where A : Clone, B: Clone; }
#[allow(non_camel_case_types)] pub trait A_SemigroupalOnce<F : A_Funct = Self> { fn a_product_once<'a,A,B>(fa : a_<'a,F,A>, fb : a_<'a,F,B>) -> a_<'a,F,(A,B)>; }
pub trait Semigroupal <F : Funct = Self> { fn product <A,B>(fa : &__<F,A>, fb : &__<F,B>) -> __<F,(A,B)> where A : Clone, B : Clone; }
pub trait SemigroupalOnce<F : Funct = Self> { fn product_once<A,B>(fa : __<F,A>, fb : __<F,B>) -> __<F,(A,B)>; }
// INVARIANT_SEMIGROUPAL
pub trait A_InvariantSemigroupal <F : A_Funct = Self> : A_Invariant<F> + A_Semigroupal<F> {}
pub trait A_InvariantSemigroupalOnce<F : A_Funct = Self> : A_InvariantOnce<F> + A_SemigroupalOnce<F> {}
impl<Impl, F> A_InvariantSemigroupal<F> for Impl where F : A_Funct, Self : A_Invariant<F> + A_Semigroupal<F> {}
impl<Impl, F> A_InvariantSemigroupalOnce<F> for Impl where F : A_Funct, Self : A_InvariantOnce<F> + A_SemigroupalOnce<F> {}
pub trait InvariantSemigroupal <F : Funct = Self> : Invariant<F> + Semigroupal<F> {}
pub trait InvariantSemigroupalOnce<F : Funct = Self> : InvariantOnce<F> + SemigroupalOnce<F> {}
impl<Impl, F> InvariantSemigroupal<F> for Impl where F : Funct, Self : Invariant<F> + Semigroupal<F> {}
impl<Impl, F> InvariantSemigroupalOnce<F> for Impl where F : Funct, Self : InvariantOnce<F> + SemigroupalOnce<F> {}
// INVARIANT MONOIDAL
pub trait InvariantMonoidal <F : Funct = Self> : FUnit<F> + InvariantSemigroupal<F> {}
pub trait InvariantMonoidalOnce<F : Funct = Self> : FUnit<F> + InvariantSemigroupalOnce<F> {}
impl<Impl, F> InvariantMonoidal<F> for Impl where F : Funct, Self : FUnit<F> + InvariantSemigroupal<F> {}
impl<Impl, F> InvariantMonoidalOnce<F> for Impl where F : Funct, Self : FUnit<F> + InvariantSemigroupalOnce<F> {}
// APPLY
#[allow(non_camel_case_types)] pub trait A_Apply <F : A_Funct = Self> : A_Functor<F> + A_InvariantSemigroupal<F> { fn a_ap <'a,A,B>(ff : &a_<'a,F, impl Fn(A)->B>, fa : &a_<'a,F,A> )-> a_<'a,F,B>; }
#[allow(non_camel_case_types)] pub trait A_ApplyOnce<F : A_Funct = Self> : A_FunctorOnce<F> + A_InvariantSemigroupalOnce<F>{ fn a_ap_once<'a,A,B>(ff : a_<'a,F, impl FnOnce(A)->B>, fa : a_<'a,F,A> )-> a_<'a,F,B>; }
pub trait Apply <F : Funct = Self> : Functor<F> + InvariantSemigroupal<F> { fn ap <A,B>(ff : &__<F, impl Fn(&A)->B>, fa : &__<F,A> )-> __<F,B>; }
pub trait ApplyOnce<F : Funct = Self> : FunctorOnce<F> + InvariantSemigroupalOnce<F>{ fn ap_once<A,B>(ff : __<F, impl FnOnce(A)->B>, fa : __<F,A> )-> __<F,B>; }
// TAIL_REC_M
#[allow(non_camel_case_types)] pub trait A_TailRecM<F : A_Funct = Self> { fn a_tail_rec_m <'a,State,Ret>( a : State, f : impl Fn(State) -> a_<'a,F,ControlFlow<Ret,State>>) -> a_<'a,F,Ret>; }
pub trait TailRecM<F : Funct = Self> { fn tail_rec_m <State,Ret>( a : State, f : impl Fn(State) -> __<F,ControlFlow<Ret,State>>) -> __<F,Ret>; }
// FLATMAP
#[allow(non_camel_case_types)] pub trait A_FlatMap <F : A_Funct = Self> : A_Apply<F> + A_TailRecM<F> { fn a_flatmap <'a,A,B>( fa : &a_<'a,F,A>, f : impl Fn(&A)->B ) -> a_<'a,F,B>; }
#[allow(non_camel_case_types)] pub trait A_FlatMapOnce<F : A_Funct = Self> : A_ApplyOnce<F> + A_TailRecM<F> { fn a_flatmap_once<'a,A,B>( fa : a_<'a,F,A>, f : impl FnOnce(A)->B) -> a_<'a,F,B>; }
pub trait FlatMap <F : Funct = Self> : Apply<F> + TailRecM<F> { fn flatmap <A,B>( fa : &__<F,A>, f : impl Fn(&A)->B ) -> __<F,B>; }
pub trait FlatMapOnce<F : Funct = Self> : ApplyOnce<F> + TailRecM<F> { fn flatmap_once<A,B>( fa : __<F,A>, f : impl FnOnce(A)->B) -> __<F,B>; }
// APPLICATIVE
pub trait Applicative <F : Funct = Self> : Apply<F> + InvariantMonoidal<F> { fn pure<A>(x : &A)->__<F,A>;}
pub trait ApplicativeOnce<F : Funct = Self> : Apply<F> + InvariantMonoidalOnce<F> { fn pure_once<A>(x : A)->__<F,A>;}
// MONAD
pub trait Monad <F : Funct = Self> : FlatMap<F> + Applicative<F> {}
pub trait MonadOnce<F : Funct = Self> : FlatMapOnce<F> + ApplicativeOnce<F> {}
impl<Impl, F> Monad <F> for Impl where F : Funct, Self : FlatMap<F> + Applicative<F> {}
impl<Impl, F> MonadOnce<F> for Impl where F : Funct, Self : FlatMapOnce<F> + ApplicativeOnce<F> {}
// SEMIGROUP
pub trait Semigroup <A = Self> { fn combine(x : &A, y : &A) -> A; }
pub trait SemigroupOnce<A = Self> { fn combine(x : A, y : A) -> A; }
// MONOID
pub trait Monoid <A = Self> : Semigroup<A> { fn empty()->A; }
pub trait MonoidOnce<A = Self> : SemigroupOnce<A> { fn empty()->A; }
// SEMIGROUP_K
pub trait SemigroipK <F : Funct = Self> { fn combine_k <A>(x : &__<F,A>, y : &__<F,A>)-> __<F,A>; }
pub trait SemigroipKOnce<F : Funct = Self> { fn combine_k_once<A>(x : __<F,A>, y : __<F,A>)-> __<F,A>; }
// MONOID_K
pub trait MonoidK<F : Funct = Self> { fn empty_k<A>()->__<F,A>; }
// COMMUTATIVE_SEMIGROUP
// this is explicitly not blanket implemented
pub trait CommutativeSemigroup <A = Self> : Semigroup<A> {}
pub trait CommutativeSemigroupOnce<A = Self> : SemigroupOnce<A> {}
// COMMUTATIVE_MONOID
pub trait CommutativeMonoid <A = Self> : Monoid<A> + CommutativeSemigroup<A> {}
pub trait CommutativeMonoidOnce<A = Self> : MonoidOnce<A> + CommutativeSemigroupOnce<A> {}
impl<Impl, A> CommutativeMonoid <A> for Impl where Self : Monoid<A> + CommutativeSemigroup<A> {}
impl<Impl, A> CommutativeMonoidOnce<A> for Impl where Self : MonoidOnce<A> + CommutativeSemigroupOnce<A> {}
// UNORDERED_FOLD
pub trait UnorderedFoldable <F : Funct = Self> { fn unordered_fold_map<A,B, C : CommutativeMonoid<B> >(fa : &__<F,A>, f : impl Fn(A)->B) -> B; }
pub trait UnorderedFoldableOnce<F : Funct = Self> { fn unordered_fold_map<A,B, C : CommutativeMonoid<B> >(fa : __<F,A>, f : impl Fn(A)->B) -> B; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment