-
-
Save laik/1a8eaec81522bd8f9ae4af8d6591f51d to your computer and use it in GitHub Desktop.
Vec and Option monads
This file contains 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
/// https://gist.github.com/edmundsmith/855fcf0cb35dd467c29a9350481f0ecf | |
struct Forall; | |
trait Unplug { | |
type F; | |
type A; | |
} | |
trait Plug<A> { | |
type Result; | |
} | |
trait Functor: Unplug+Plug<<Self as Unplug>::A> { | |
fn map<B, F>(self, f:F) -> <Self as Plug<B>>::Result | |
where | |
Self:Plug<B>, | |
F:FnMut(<Self as Unplug>::A) -> B | |
; | |
} | |
trait Applicative: Functor { | |
fn pure(s:<Self as Unplug>::A) -> Self; | |
fn app<B, F>( | |
self, f:<Self as Plug<F>>::Result, | |
) -> <Self as Plug<B>>::Result | |
where | |
F:FnMut(<Self as Unplug>::A) -> B + Clone, | |
Self:Plug<F> + Plug<B> + Unplug, | |
<Self as Plug<F>>::Result: | |
Unplug<F=<Self as Unplug>::F,A=F> + | |
Plug<F> + | |
Clone, | |
<Self as Unplug>::F:Plug<F> | |
; | |
} | |
trait Monad : Applicative { | |
fn bind<F,B>(self, f:F) -> <Self as Plug<B>>::Result | |
where | |
Self:Plug<F>+Plug<B>, | |
F:FnMut(<Self as Unplug>::A) -> | |
<Self as Plug<B>>::Result + Clone | |
; | |
} | |
// -------------- | |
impl<A,B> Plug<A> for Vec<B> { | |
type Result = Vec<A>; | |
} | |
impl<A> Unplug for Vec<A> { | |
type F=Vec<Forall>; | |
type A=A; | |
} | |
impl<A> Functor for Vec<A> { | |
fn map<B,F>(self, f:F) -> <Self as Plug<B>>::Result | |
where | |
F:FnMut(<Self as Unplug>::A) -> B | |
{ | |
self.into_iter().map(f).collect() | |
} | |
} | |
impl<A:Clone> Applicative for Vec<A> { | |
fn pure(a:A) -> Self { | |
vec![a] | |
} | |
fn app<B, F>( | |
self, fs:<Self as Plug<F>>::Result | |
) -> <Self as Plug<B>>::Result | |
where | |
F:FnMut(<Self as Unplug>::A) -> B + Clone, | |
<Self as Plug<F>>::Result: Clone, | |
{ | |
self.map(|x| | |
fs.clone().map(|f| f.clone()(x.clone()))) | |
.into_iter() | |
.map(|x|x) | |
.flatten() | |
.collect() | |
} | |
} | |
impl<A:Clone> Monad for Vec<A> { | |
fn bind<F,B>(self, mut f:F) -> | |
<Self as Plug<B>>::Result | |
where | |
F:FnMut(<Self as Unplug>::A) | |
-> <Self as Plug<B>>::Result | |
{ | |
self | |
.into_iter() | |
.map(|x| f(x)) | |
.flatten().collect() | |
} | |
} | |
fn vec_monad() { | |
fn x2(x: i32) -> i32 { x * 2 } | |
fn x20(x: i32) -> i32 { x * 20 } | |
let v = vec![1, 2, 3].app(vec![x2 as fn(i32) -> i32, x20]).bind(|x| vec![x + 100]); | |
println!("{:?}", v); | |
} | |
impl<A, B> Plug<B> for Option<A> { | |
type Result = Option<B>; | |
} | |
impl<A> Unplug for Option<A> { | |
type F = Option<Forall>; | |
type A = A; | |
} | |
impl<A> Functor for Option<A> { | |
fn map<B,F>(self, mut f:F) -> <Self as Plug<B>>::Result | |
where | |
F:FnMut(<Self as Unplug>::A) -> B | |
{ | |
match self { | |
Some(a) => Some(f(a)), | |
None => None, | |
} | |
} | |
} | |
impl<A> Applicative for Option<A> { | |
fn pure(a: Self::A) -> Self { | |
Some(a) | |
} | |
fn app<B, F>( | |
self, fs:<Self as Plug<F>>::Result | |
) -> <Self as Plug<B>>::Result | |
where | |
F:FnMut(<Self as Unplug>::A) -> B, | |
{ | |
match fs { | |
Some(f) => self.map(f), | |
None => None, | |
} | |
} | |
} | |
impl<A> Monad for Option<A> { | |
fn bind<F,B>(self, mut f:F) -> | |
<Self as Plug<B>>::Result | |
where | |
F:FnMut(<Self as Unplug>::A) | |
-> <Self as Plug<B>>::Result | |
{ | |
match self { | |
Some(a) => f(a), | |
None => None, | |
} | |
} | |
} | |
fn option_monad() { | |
let v = Some(1).bind(|x| Some(x * 2)).app(Some(|x| x + 1)); | |
println!("{:?}", v); | |
} | |
fn main() { | |
vec_monad(); | |
option_monad(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment