package sbt object Classes { trait Applicative[M[_]] { def apply[S,T](f: M[S => T], v: M[S]): M[T] def pure[S](s: => S): M[S] def map[S, T](f: S => T, v: M[S]): M[T] } trait Monad[M[_]] extends Applicative[M] { def flatten[T](m: M[M[T]]): M[T] } implicit val optionMonad: Monad[Option] = new Monad[Option] { def apply[S,T](f: Option[S => T], v: Option[S]) = (f, v) match { case (Some(fv), Some(vv)) => Some(fv(vv)); case _ => None } def pure[S](s: => S) = Some(s) def map[S, T](f: S => T, v: Option[S]) = v map f def flatten[T](m: Option[Option[T]]): Option[T] = m.flatten } implicit val listMonad: Monad[List] = new Monad[List] { def apply[S,T](f: List[S => T], v: List[S]) = for(fv <- f; vv <- v) yield fv(vv) def pure[S](s: => S) = s :: Nil def map[S, T](f: S => T, v: List[S]) = v map f def flatten[T](m: List[List[T]]): List[T] = m.flatten } }