Skip to content

Instantly share code, notes, and snippets.

@burjui

burjui/main.rs

Last active Nov 11, 2020
Embed
What would you like to do?
Vec and Option monads
/// 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();
}
@GrayJack

This comment has been minimized.

Copy link

@GrayJack GrayJack commented Aug 14, 2019

Why can't we define app as

impl<A:Clone> 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 + Clone,
            <Self as Plug<F>>::Result: Clone,
    {
         match fs {
             Some(f) => self.fmap(f),
             None => None,
          }
    }
}
@burjui

This comment has been minimized.

Copy link
Owner Author

@burjui burjui commented Aug 15, 2019

Because I, being a lazy ass, instead of thinking hard about it, just applied an ancient technique to the original Edmund's code, known as copy-paste-fix-compile loop. Thanks for the suggestion, now this pile of crap looks a bit nicer 😄

@GrayJack

This comment has been minimized.

Copy link

@GrayJack GrayJack commented Aug 15, 2019

I'm doing this for my Category Class: https://github.com/GrayJack/gat
Where I'm implementing those thinks in Rust.

I had some headache implementing them, googling about it I found the Edmund's code.
If you want to, you can check it out my impl for Option, Result, Vec and LinkedList, but it lacks Monads

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment