Skip to content

Instantly share code, notes, and snippets.

@mschuwalow
Last active November 18, 2020 16:56
Show Gist options
  • Select an option

  • Save mschuwalow/3f0dde829295280a6d9ba20743c712b7 to your computer and use it in GitHub Desktop.

Select an option

Save mschuwalow/3f0dde829295280a6d9ba20743c712b7 to your computer and use it in GitHub Desktop.

Revisions

  1. mschuwalow revised this gist Nov 18, 2020. 1 changed file with 144 additions and 36 deletions.
    180 changes: 144 additions & 36 deletions hkt.rs
    Original file line number Diff line number Diff line change
    @@ -1,73 +1,83 @@
    trait Family {
    type Member<T>: Mirror<T, Family = Self>;
    use std::marker::PhantomData;

    trait Family<'a> {
    type Member<T: 'a>: Mirror<'a, T, Family = Self>;
    }
    trait Mirror<T> {
    type Family: Family;
    fn as_member(self) -> <Self::Family as Family>::Member<T>;
    trait Mirror<'a, T> {
    type Family: Family<'a>;
    fn as_member(self) -> <Self::Family as Family<'a>>::Member<T>;
    }

    trait Functor: Family {
    fn fmap<A, B, F: FnMut(A) -> B>(
    fa: <Self as Family>::Member<A>,
    trait Functor<'a>: Family<'a> {
    fn fmap<A: 'a, B: 'a, F: FnMut(A) -> B + 'a>(
    fa: <Self as Family<'a>>::Member<A>,
    f: F,
    ) -> <Self as Family>::Member<B>;
    ) -> <Self as Family<'a>>::Member<B>;
    }

    trait FunctorSyntax<A, Fam: Functor>: Mirror<A, Family = Fam> + Sized {
    fn fmap<B, F: FnMut(A) -> B>(self, f: F) -> <Fam as Family>::Member<B> {
    trait FunctorSyntax<'a, A: 'a, Fam: Functor<'a>>:
    Mirror<'a, A, Family = Fam> + Sized
    {
    fn fmap<B, F: FnMut(A) -> B + 'a>(
    self,
    f: F,
    ) -> <Fam as Family<'a>>::Member<B> {
    <Fam as Functor>::fmap(self.as_member(), f)
    }
    }

    impl<A, F: Functor, T: Mirror<A, Family = F>> FunctorSyntax<A, F> for T {}
    impl<'a, A: 'a, F: Functor<'a>, T: Mirror<'a, A, Family = F>>
    FunctorSyntax<'a, A, F> for T
    {
    }

    trait Applicative: Functor {
    fn pure<A>(a: A) -> <Self as Family>::Member<A>;
    fn zip<A, B>(
    fa: <Self as Family>::Member<A>,
    fb: <Self as Family>::Member<B>,
    ) -> <Self as Family>::Member<(A, B)>;
    trait Applicative<'a>: Functor<'a> {
    fn pure<A: 'a>(a: A) -> <Self as Family<'a>>::Member<A>;
    fn zip<A: 'a, B: 'a>(
    fa: <Self as Family<'a>>::Member<A>,
    fb: <Self as Family<'a>>::Member<B>,
    ) -> <Self as Family<'a>>::Member<(A, B)>;
    }

    fn pure<F: Applicative, A>(a: A) -> F::Member<A> {
    fn pure<'a, F: Applicative<'a>, A: 'a>(a: A) -> F::Member<A> {
    <F as Applicative>::pure(a)
    }

    trait ApplicativeSyntax<A, Fam: Applicative>:
    Mirror<A, Family = Fam> + Sized
    trait ApplicativeSyntax<'a, A: 'a, Fam: Applicative<'a>>:
    Mirror<'a, A, Family = Fam> + Sized
    {
    fn zip<B>(
    fn zip<B: 'a>(
    self,
    fb: <Fam as Family>::Member<B>,
    ) -> <Fam as Family>::Member<(A, B)> {
    fb: <Fam as Family<'a>>::Member<B>,
    ) -> <Fam as Family<'a>>::Member<(A, B)> {
    <Fam as Applicative>::zip(self.as_member(), fb)
    }
    }

    impl<A, F: Applicative, T: Mirror<A, Family = F>> ApplicativeSyntax<A, F>
    for T
    impl<'a, A: 'a, F: Applicative<'a>, T: Mirror<'a, A, Family = F>>
    ApplicativeSyntax<'a, A, F> for T
    {
    }

    // usage
    // option

    struct OptionFamily;
    impl Family for OptionFamily {
    type Member<T> = Option<T>;
    impl<'a> Family<'a> for OptionFamily {
    type Member<T: 'a> = Option<T>;
    }
    impl<A> Mirror<A> for Option<A> {
    impl<'a, A: 'a> Mirror<'a, A> for Option<A> {
    type Family = OptionFamily;

    fn as_member(self) -> Option<A> {
    self
    }
    }
    impl Functor for OptionFamily {
    impl<'a> Functor<'a> for OptionFamily {
    fn fmap<A, B, F: FnMut(A) -> B>(fa: Option<A>, f: F) -> Option<B> {
    fa.map(f)
    }
    }
    impl Applicative for OptionFamily {
    impl<'a> Applicative<'a> for OptionFamily {
    fn pure<A>(a: A) -> Option<A> {
    Some(a)
    }
    @@ -80,8 +90,106 @@ impl Applicative for OptionFamily {
    }
    }

    fn use_applicative<F: Applicative>(i: i32) -> F::Member<(i32, i32)> {
    let fa = pure::<F, _>(i);
    let fb = pure::<F, _>(i);
    fa.fmap(|x| x + 1).zip(fb)
    // result

    struct ResultFamily<'a, E: 'a> {
    phantom: PhantomData<&'a E>,
    }
    impl<'a, E: 'a> Family<'a> for ResultFamily<'a, E> {
    type Member<T: 'a> = Result<T, E>;
    }
    impl<'a, A: 'a, E: 'a> Mirror<'a, A> for Result<A, E> {
    type Family = ResultFamily<'a, E>;

    fn as_member(self) -> <Self::Family as Family<'a>>::Member<A> {
    self
    }
    }
    impl<'a, E: 'a> Functor<'a> for ResultFamily<'a, E> {
    fn fmap<A, B, F: FnMut(A) -> B>(fa: Result<A, E>, f: F) -> Result<B, E> {
    fa.map(f)
    }
    }
    impl<'a, E: 'a> Applicative<'a> for ResultFamily<'a, E> {
    fn pure<A>(a: A) -> Result<A, E> {
    Ok(a)
    }

    fn zip<A, B>(fa: Result<A, E>, fb: Result<B, E>) -> Result<(A, B), E> {
    fa.and_then(|a| fb.map(|b| (a, b)))
    }
    }

    // iterator

    struct IteratorWrap<'a, T>(Box<dyn Iterator<Item = T> + 'a>);
    trait IteratorSyntax<'a, T: Sized>: Iterator<Item = T> + Sized + 'a {
    fn wrap(self) -> IteratorWrap<'a, T> {
    IteratorWrap(Box::new(self))
    }
    }
    impl<'a, T, I: Iterator<Item = T> + 'a> IteratorSyntax<'a, T> for I {}
    impl<'a, T> Iterator for IteratorWrap<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
    self.0.next()
    }
    }

    struct IteratorWrapFamily;
    impl<'a> Family<'a> for IteratorWrapFamily {
    type Member<T: 'a> = IteratorWrap<'a, T>;
    }
    impl<'a, T: 'a> Mirror<'a, T> for IteratorWrap<'a, T> {
    type Family = IteratorWrapFamily;

    fn as_member(self) -> <Self::Family as Family<'a>>::Member<T> {
    self
    }
    }
    impl<'a> Functor<'a> for IteratorWrapFamily {
    fn fmap<A: 'a, B, F: FnMut(A) -> B + 'a>(
    fa: IteratorWrap<'a, A>,
    f: F,
    ) -> IteratorWrap<'a, B> {
    IteratorWrap(Box::new(fa.0.into_iter().map(f).into_iter()))
    }
    }
    impl<'a> Applicative<'a> for IteratorWrapFamily {
    fn pure<A: 'a>(a: A) -> IteratorWrap<'a, A> {
    vec![a].into_iter().wrap()
    }

    fn zip<A: 'a, B: 'a>(
    fa: IteratorWrap<A>,
    fb: IteratorWrap<B>,
    ) -> IteratorWrap<'a, (A, B)> {
    let mut result = Vec::new();
    let mut fa = fa;
    let mut fb = fb;
    while let (Some(a), Some(b)) = (fa.next(), fb.next()) {
    result.push((a, b));
    }
    result.into_iter().wrap()
    }
    }

    // usage

    fn use_applicative<'a, A, F: Applicative<'a>>(a: A, b: A) -> F::Member<(A, A)> {
    let fa = pure::<F, _>(a);
    let fb = pure::<F, _>(b);
    fa.zip(fb)
    }

    fn foo() -> Option<(i32, i32)> {
    let a = Some(3);
    let b = a.fmap(|x| (x + 1, x));
    b
    }

    fn use_iterator() -> IteratorWrap<'static, i32> {
    let v = vec![1];
    v.into_iter().wrap().fmap(|x| x + 1).fmap(|x| x + 1)
    }
  2. mschuwalow renamed this gist Nov 17, 2020. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  3. mschuwalow created this gist Nov 17, 2020.
    87 changes: 87 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,87 @@
    trait Family {
    type Member<T>: Mirror<T, Family = Self>;
    }
    trait Mirror<T> {
    type Family: Family;
    fn as_member(self) -> <Self::Family as Family>::Member<T>;
    }

    trait Functor: Family {
    fn fmap<A, B, F: FnMut(A) -> B>(
    fa: <Self as Family>::Member<A>,
    f: F,
    ) -> <Self as Family>::Member<B>;
    }

    trait FunctorSyntax<A, Fam: Functor>: Mirror<A, Family = Fam> + Sized {
    fn fmap<B, F: FnMut(A) -> B>(self, f: F) -> <Fam as Family>::Member<B> {
    <Fam as Functor>::fmap(self.as_member(), f)
    }
    }

    impl<A, F: Functor, T: Mirror<A, Family = F>> FunctorSyntax<A, F> for T {}

    trait Applicative: Functor {
    fn pure<A>(a: A) -> <Self as Family>::Member<A>;
    fn zip<A, B>(
    fa: <Self as Family>::Member<A>,
    fb: <Self as Family>::Member<B>,
    ) -> <Self as Family>::Member<(A, B)>;
    }

    fn pure<F: Applicative, A>(a: A) -> F::Member<A> {
    <F as Applicative>::pure(a)
    }

    trait ApplicativeSyntax<A, Fam: Applicative>:
    Mirror<A, Family = Fam> + Sized
    {
    fn zip<B>(
    self,
    fb: <Fam as Family>::Member<B>,
    ) -> <Fam as Family>::Member<(A, B)> {
    <Fam as Applicative>::zip(self.as_member(), fb)
    }
    }

    impl<A, F: Applicative, T: Mirror<A, Family = F>> ApplicativeSyntax<A, F>
    for T
    {
    }

    // usage

    struct OptionFamily;
    impl Family for OptionFamily {
    type Member<T> = Option<T>;
    }
    impl<A> Mirror<A> for Option<A> {
    type Family = OptionFamily;

    fn as_member(self) -> Option<A> {
    self
    }
    }
    impl Functor for OptionFamily {
    fn fmap<A, B, F: FnMut(A) -> B>(fa: Option<A>, f: F) -> Option<B> {
    fa.map(f)
    }
    }
    impl Applicative for OptionFamily {
    fn pure<A>(a: A) -> Option<A> {
    Some(a)
    }

    fn zip<A, B>(fa: Option<A>, fb: Option<B>) -> Option<(A, B)> {
    match (fa, fb) {
    (Some(a), Some(b)) => Some((a, b)),
    _ => None,
    }
    }
    }

    fn use_applicative<F: Applicative>(i: i32) -> F::Member<(i32, i32)> {
    let fa = pure::<F, _>(i);
    let fb = pure::<F, _>(i);
    fa.fmap(|x| x + 1).zip(fb)
    }