Namdak Tonpa (maxim) wrote,
Namdak Tonpa
maxim

HKT in Rust

Компилирующийся код! А в этом журнале — это редкость, полноценные монадки на расте:


pub trait HKT<u> {
    type C; // Current type
    type T; // Type with C swapped with U
}

macro_rules! derive_hkt {
    ($t:ident) => {
        impl HKT<u> for $t<t> {
            type C = T;
            type T = $t<u>;
        }
    }
}

pub trait Functor<U>: HKT<U> {
    fn map<F>(&self, f: F) -> Self::T where F: Fn(&Self::C) -> U;
}

pub trait Applicative<U>: Functor<U> {
    fn pure_(value: U) -> Self::T where Self: HKT<U, C=U>;
    fn seq<F>(&self, <Self as HKT<F>>::T) -> 
       <Self as HKT<U>>::T where Self: HKT<F>, 
          F: Fn(&<Self as HKT<F>>::C) -> U;
}

pub trait Monad<U>: Applicative<U> {
    fn bind<F>(&self, F) -> Self::T where F : FnMut(&Self::C) -> Self::T;

    fn return_(x: U) -> Self::T where Self: HKT<U, C=U> {
        Self::pure_(x)
    }

    fn join<T>(&self) -> T where Self: HKT<U, T=T, C=T>, T: Clone {
        self.bind(|x| x.clone())
    }
}

impl<T, U> Functor<U> for Vec<T> {
    fn map<F>(&self, f: F) -> Vec<U> where F: Fn(&T) -> U {
        let mut result = Vec::with_capacity(self.len());
        for value in self {
            result.push( f(value) );
        }
        result
    }
}

impl<T, U> Applicative<U> for Vec<T> {
    fn pure_(value: U) -> <Self as HKT<U>>::T { vec![value] }

    fn seq<F>(&self, fs: <Self as HKT<F>>::T) -> 
      <Self as HKT<U>>::T where F: Fn(&<Self as HKT<F>>::C) -> U {
        let mut result = vec![];
        for (i, f) in fs.into_iter().enumerate() {
            let v = (f)( &self[i] );
            result.push(v)
        }
        return result;
    }
}

impl<T, U> Monad<U> for Vec<T> {
    fn bind<F>(&self, mut f: F) -> Vec<U> where F : FnMut(&T) -> Vec<U> {
        let mut result = vec![];
        for x in self {
            let v = f(x);
            result.extend(v);
        }
        result
    }
}

derive_hkt!(Vec);

fn test() {
        let v = Vec::return_(1);
        let v = v.bind(|x| vec![x.to_string(); 3]);
        println!("{:?}", v);

        let v = vec![vec!(true), vec!(false)];
        let v = v.join();
        println!("{:?}", v);
}
Tags: cs
  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

  • 9 comments