Created
February 24, 2026 16:48
-
-
Save l-Luna/4a32d8bbc269aef142f42f7246ba14d2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::marker::PhantomData; | |
| // monad trait | |
| trait Monad{ | |
| type App<T>; | |
| fn pure<T>(x: T) -> Self::App<T>; | |
| fn bind<T, U>(x: Self::App<T>, f: impl Fn(T) -> Self::App<U>) -> Self::App<U>; | |
| } | |
| // do-notation | |
| macro_rules! mdo{ | |
| // binds: let &a = b; | |
| ($t:ty | let! $i:ident = $e:expr; $($k:tt)*) => { <$t>::bind($e, |$i| mdo!( $t | $($k)* ) ) }; | |
| // non-monadic let | |
| ($t:ty | let $i:ident = $e:expr; $($k:tt)*) => { { let $i = $e; mdo!( $t | $($k)* ) } }; | |
| // wrapping and non-wrapping returns | |
| ($t:ty | pure $e:expr) => { <$t>::pure($e) }; | |
| ($t:ty | exact $e:expr) => { ($e) }; | |
| } | |
| // concrete monads | |
| struct Identity; | |
| impl Monad for Identity{ | |
| type App<T> = T; | |
| fn pure<T>(x: T) -> T { | |
| x | |
| } | |
| fn bind<T, U>(x: T, f: impl Fn(T) -> U) -> U { | |
| f(x) | |
| } | |
| } | |
| struct Vecs; | |
| impl Monad for Vecs{ | |
| type App<T> = Vec<T>; | |
| fn pure<T>(x: T) -> Vec<T>{ | |
| vec![x] | |
| } | |
| fn bind<T, U>(xs: Vec<T>, f: impl Fn(T) -> Vec<U>) -> Vec<U>{ | |
| let mut tmp: Vec<U> = vec![]; | |
| for x in xs{ | |
| tmp.extend(f(x)); | |
| } | |
| tmp | |
| } | |
| } | |
| // monad transformer trait | |
| trait MonadTrans{ | |
| type Trans<M: Monad>: Monad; | |
| fn lift<M: Monad, T>(x: M::App<T>) -> <Self::Trans<M> as Monad>::App<T>; | |
| } | |
| // concrete monad transformers | |
| struct MaybeT<M: Monad>{ _ty: PhantomData<M> } | |
| impl<M: Monad> Monad for MaybeT<M>{ | |
| type App<T> = M::App<Option<T>>; | |
| fn pure<T>(x: T) -> M::App<Option<T>> { | |
| M::pure(Some(x)) | |
| } | |
| fn bind<T, U>(x: M::App<Option<T>>, f: impl Fn(T) -> M::App<Option<U>>) -> M::App<Option<U>> { | |
| mdo!{ M | | |
| let! v = x; | |
| exact match v { | |
| Some(vv) => f(vv), | |
| None => M::pure(None) | |
| } | |
| } | |
| } | |
| } | |
| struct MaybeTS; | |
| impl MonadTrans for MaybeTS{ | |
| type Trans<M: Monad> = MaybeT<M>; | |
| fn lift<M: Monad, T>(x: M::App<T>) -> M::App<Option<T>> { | |
| mdo!{ M | | |
| let! v = x; | |
| pure Some(v) | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment