funlib 0.1.7

Rust functional library
Documentation
//!
//! Applicative implementations and tests
//! 
use crate::Applicative;
use crate::HKT;
use std::rc::Rc;

impl<A, B> Applicative<B> for Option<A> {
  fn pure_(b: B) -> <Self as HKT<B>>::M {
    Some(b)
  }

  fn ap<F>(&self, of: <Self as HKT<F>>::M) -> Option<B> where  F: Fn(&A) -> B {
    match (self, of) {
      (&Some(ref a), Some(ref f)) => Some(f(a)),
      (_, _) => None
    }
  }
}

impl<A, B> Applicative<B> for Box<A> {
  fn pure_(b: B) -> <Self as HKT<B>>::M {
    Box::new(b)
  }

  fn ap<F>(&self, of: <Self as HKT<F>>::M) -> Box<B> where F: Fn(&A) -> B {
    Box::new(of(self))
  }
}

impl<A, B> Applicative<B> for Rc<A> {
  fn pure_(b: B) -> <Self as HKT<B>>::M {
    Rc::new(b)
  }

  fn ap<F>(&self, of: <Self as HKT<F>>::M) -> Rc<B> where F: Fn(&A) -> B {
    Rc::new(of(self))
  }
}

impl<A, B> Applicative<B> for Vec<A> {
  fn pure_(b: B) -> <Self as HKT<B>>::M {
    vec![b]
  }

  fn ap<F>(&self, of: <Self as HKT<F>>::M) -> Vec<B> where F: Fn(&A) -> B {
    let mut result = vec![];
    for (i,f) in of.into_iter().enumerate() {
      result.push(f(&self[i]))
    }
    result
  }
}

#[cfg(test)]
mod test {
  use crate::Applicative;
  use std::rc::Rc;

  fn double(i: &i32) -> i32 { i * 2 }

  #[test]
  fn option() {
    let f: &dyn Fn(&i32) -> i32 = &|x| x * 2;
    assert_eq!(Some(4), Some(2).ap(Some(f)));
    assert_eq!(Some(4), Some(2).ap(Some(&double)));
  }

  #[test]
  fn box_() {
    let f: &dyn Fn(&i32) -> i32 = &|x| x * 2;
    assert_eq!(Box::new(4), Box::new(2).ap(Box::new(f)));
    assert_eq!(Box::new(4), Box::new(2).ap(Box::new(&double)));
  }

  #[test]
  fn rc() {
    let f: &dyn Fn(&i32) -> i32 = &|x| x * 2;
    assert_eq!(Rc::new(4), Rc::new(2).ap(Rc::new(f)));
    assert_eq!(Rc::new(4), Rc::new(2).ap(Rc::new(&double)));
  }

  #[test]
  fn vec() {
    let f1: &dyn Fn(&i32) -> i32 = &|x| x + 6;
    let f2: &dyn Fn(&i32) -> i32 = &|x| x * x;
    let f3: &dyn Fn(&i32) -> i32 = &|x| x * x * x;
    assert_eq!(vec![7,4,27], vec![1,2,3].ap(vec![f1,f2,f3]))
  }
}