Skip to content

Instantly share code, notes, and snippets.

@laik
Forked from burjui/main.rs
Created March 10, 2020 06:50
Show Gist options
  • Save laik/1a8eaec81522bd8f9ae4af8d6591f51d to your computer and use it in GitHub Desktop.
Save laik/1a8eaec81522bd8f9ae4af8d6591f51d to your computer and use it in GitHub Desktop.
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();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment