Skip to content

Instantly share code, notes, and snippets.

@Jeffrey04
Last active August 1, 2018 09:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jeffrey04/14649da1b62de82b0101ed28079dd5c3 to your computer and use it in GitHub Desktop.
Save Jeffrey04/14649da1b62de82b0101ed28079dd5c3 to your computer and use it in GitHub Desktop.
pub trait Functor<F, V> {
fn fmap(self, func: F) -> V;
}
pub trait Monad<F, U> {
fn bind(self, func: F) -> U;
}
pub trait Applicative<F, U> {
fn lift(self, func: F) -> U;
}
impl<F: Fn(i32) -> i32> Functor<F, Option<i32>> for Option<i32> {
fn fmap(self, func: F) -> Option<i32> {
self.map(func)
}
}
impl<F: Fn(i32) -> i32> Functor<F, Vec<i32>> for Vec<i32> {
fn fmap(self, func: F) -> Vec<i32> {
self.into_iter().map(|x| func(x)).collect()
}
}
impl<F1: 'static + Fn(i32) -> i32, F: 'static + Fn(i32) -> i32> Functor<F, Box<Fn(i32) -> i32>> for F1 {
fn fmap(self, func: F) -> Box<Fn(i32) -> i32> {
Box::new(move |x| {
func(self(x))
})
}
}
impl<F: 'static + Fn(i32, i32) -> i32> Functor<Option<F>, Option<Box<Fn(i32) -> i32>>> for Option<i32> {
fn fmap(self, func: Option<F>) -> Option<Box<Fn(i32) -> i32>> {
match(self, func) {
(Some(n), Some(f)) => Some(Box::new(move |x| f(x, n))),
_ => None
}
}
}
impl<F: Fn(i32) -> i32> Applicative<Option<F>, Option<i32>> for Option<i32> {
fn lift(self, func: Option<F>) -> Option<i32> {
match (self, func) {
(Some(n), Some(f)) => Some(f(n)),
_ => None
}
}
}
impl Applicative<Option<i32>, Option<i32>> for Option<Box<Fn(i32) -> i32>> {
fn lift(self, value: Option<i32>) -> Option<i32> {
match(self, value) {
(Some(f), Some(n)) => Some(f(n)),
_ => None
}
}
}
impl<F: Fn(i32) -> Option<i32>> Monad<F, Option<i32>> for Option<i32> {
fn bind(self, func: F) -> Option<i32> {
self.and_then(func)
}
}
pub fn main() {
println!("Functor (wrapped value) {:?}", Some(1).fmap(|x| x * 2));
println!("Functor (vec) {:?}", vec![1, 2, 3].fmap(|x| x * 2));
println!("Functor (function composition) {:?}", (|x| x + 1).fmap(|x| x * 2)(2));
println!("Applicative {:?}", Some(2).lift(Some(|x| x + 3)));
println!("Functor + Applicative {:?}", Some(2).fmap(Some(|x, y| x + y)).lift(Some(5)));
let half = |x: i32| -> Option<i32> {match x % 2 {
0 => Some(x / 2),
_ => None
}};
println!("Monad {:?}", Some(1).bind(|x| Some(x + 1)));
println!("Monad {:?}", Some(20).bind(half));
println!("Monad {:?}", Some(20).bind(half).bind(half));
println!("Monad {:?}", Some(20).bind(half).bind(half).bind(half));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment