functional 0.0.7

Functional traits
use control::functor::Functor;
use control::applicative::Applicative;
use control::monad::Monad;
use algebra::{Monoid, Prod, Sum, Sequence};

use std::fmt;


#[test]
fn test_functor() {
    let f = |x| x * 2;
    assert!(Some(1).fmap(&f) == Some(2));
    assert!(None.fmap(&f) == None);
}

#[test]
fn test_monad() {
    let f = |x| Some(x * 2);
    assert!(Some(1).fmap(&f).join() == Some(1).bind(&f));
    assert!(None.fmap(&f).join() == None.bind(&f));
}


#[test]
fn test_applicative() {
    let f = |x| x * 2;
    assert_eq!(Some(&f).ap(Some(3)), Some(6));
    assert_eq!(Some(&f).ap(None), None);

    let none: Option<fn(i32) -> i32> = None;
    assert_eq!(none.ap(Some(3)), None);
    assert_eq!(none.ap(None), None);
}


fn check_monoid<M>(monoid: M)
    where M: Monoid + PartialEq + Clone + fmt::Debug
{
    assert_eq!(monoid.clone().mappend(M::mempty()), monoid.clone());
    assert_eq!(M::mempty().mappend(monoid.clone()), monoid.clone());
}


#[test]
fn test_monoid() {
    check_monoid(Sum(12.3));
    check_monoid(Sum(4));
    check_monoid(Prod(12.3));
    check_monoid(Prod(4));
    check_monoid(Sequence(vec![1, 2, 3]));
}