这个例子来源于scala圣经级教程《Functional Programming in Scala》,虽然原书的随书代码可以找到这些类的影子,但却没有关于如何使用这些类的示例代码,本人在阅读此书期间,除了跟着书中的代码敲了一遍之外,还写了一些测试代码进行验证,贴出来作为blog主要是为了方便自己,也为那些同样在阅读此书的人参考, 因为或许有可能你看了书本也不知道如何使用这些现成的函数和库。注释不多,本人也不可能写太多,因为这本书不是简单的入门书,而是一本进阶,升华用的内涵书籍,三言两语也解释不清其中的很多细节,如果看不懂,但是又感兴趣的就去看原书吧……
package applicative
import monad.Functor
import monoids._
import state.State._
import state._
import scala.language.{higherKinds, implicitConversions}
trait Applicative[F[_]] extends Functor[F] {
// `map2` is implemented by first currying `f` so we get a function// of type `A => B => C`. This is a function that takes `A` and returns// another function of type `B => C`. So if we map `f.curried` over an// `F[A]`, we get `F[B => C]`. Passing that to `apply` along with the// `F[B]` will give us the desired `F[C]`.
def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] =
apply(map(fa)(f.curried))(fb)
// We simply use `map2` to lift a function into `F` so we can apply it// to both `fab` and `fa`. The function being lifted here is `_(_)`,// which is the same as the lambda notation `(f, x) => f(x)`. That is,// It's a function that takes two arguments:// 1. A function `f`// 2. An argument `x` to that function// and it simply applies `f` to `x`.
def apply[A,B](fab: F[A => B])(fa: F[A]): F[B] =
map2(fab, fa)(_(_))
def unit[A](a: => A): F[A]
def map[A,B](fa: F[A])(f: A => B): F[B] =
apply(unit(f))(fa)
def sequence[A](fas: List[F[A]]): F[List[A]] =
traverse(fas)(fa => fa)
def traverse[A,B](as: List[A])(f: A => F[B]): F[List[B]] =
as.foldRight(unit(List[B]()))((a, fbs) => map2(f(a), fbs)(_ :: _))
def replicateM[A](n: Int, fa: F[A]): F[List[A]] =
sequence(List.fill(n)(fa))
def factor[A,B](fa: F[A], fb: F[B]): F[(A,B)] =
map2(fa, fb)((_,_))
def product[G[_]](G: Applicative[G]): Applicative[({type f[x] = (F[x], G[x])})#f] = {
val self = thisnew Applicative[({type f[x] = (F[x], G[x])})#f] {
def unit[A](a: => A) = (self.unit(a), G.unit(a))
override def apply[A,B](fs: (F[A => B], G[A => B]))(p: (F[A], G[A])) =
(self.apply(fs._1)(p._1), G.apply(fs._2)(p._2))
}
}
// Here we simply use `map2` to lift `apply` and `unit` themselves from one// Applicative into the other.// If `self` and `G` both satisfy the laws, then so does the composite.// The full proof can be found at// https://github.com/runarorama/sannanir/blob/master/Applicative.v
def compose[G[_]](G: Applicative[G]): Applicative[({type f[x] = F[G[x]]})#f] = {
val self = thisnew Applicative[({type f[x] = F[G[x]]})#f] {
def unit[A](a: => A) = self.unit(G.unit(a))
override def map2[A,B,C](fga: F[G[A]], fgb: F[G[B]])(f: (A,B) => C) =
self.map2(fga, fgb)(G.map2(_,_)(f))
}
}
def sequenceMap[K,V](ofa: Map[K,F[V]]): F[Map[K,V]] =
(ofa foldLeft unit(Map.empty[K,V])) { case (acc, (k, fv)) =>
map2(acc, fv)((m, v) => m + (k -> v))
}
}
sealed trait Validation[+E, +A]
case class Failure[E](head: E, tail: Vector[E])
extends Validation[E, Nothing]
case class Success[A](a: A) extends Validation[Nothing, A]
object Applicative {
val streamApplicative = new Applicative[Stream] {
def unit[A](a: => A): Stream[A] =
Stream.continually(a) // The infinite, constant stream
override def map2[A,B,C](a: Stream[A], b: Stream[B])( // Combine elements pointwise
f: (A,B) => C): Stream[C] =
a zip b map f.tupled
}
def validationApplicative[E]: Applicative[({type f[x] = Validation[E,x]})#f] =
new Applicative[({type f[x] = Validation[E,x]})#f] {
def unit[A](a: => A) = Success(a)
override def map2[A,B,C](fa: Validation[E,A], fb: Validation[E,B])(f: (A, B) => C) =
(fa, fb) match {
case (Success(a), Success(b)) => Success(f(a, b))
case (Failure(h1, t1), Failure(h2, t2)) =>
Failure(h1, t1 ++ Vector(h2) ++ t2)
case (e@Failure(_, _), _) => e
case (_, e@Failure(_, _)) => e
}
}
type Const[A, B] = A
implicit def monoidApplicative[M](M: Monoid[M]) =
new Applicative[({ type f[x] = Const[M, x] })#f] {
def unit[A](a: => A): M = M.zero
override def apply[A,B](m1: M)(m2: M): M = M.op(m1, m2)
}
}
trait Monad[F[_]] extends Applicative[F] {
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] =
join(map(ma)(f))
override def apply[A,B](mf: F[A => B])(ma: F[A]): F[B] =
flatMap(mf)(f => map(ma)(f))
override def map[A,B](m: F[A])(f: A => B): F[B] =
flatMap(m)(a => unit(f(a)))
override def map2[A,B,C](ma: F[A], mb: F[B])(f: (A, B) => C): F[C] =
flatMap(ma)(a => map(mb)(b => f(a, b)))
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] =
a => flatMap(f(a))(g)
def join[A](mma: F[F[A]]): F[A] = flatMap(mma)(ma => ma)
}
object Monad {
// Notice that in the case of a `Left`, flatMap does nothing.
def eitherMonad[E]: Monad[({type f[x] = Either[E, x]})#f] =
new Monad[({type f[x] = Either[E, x]})#f] {
def unit[A](a: => A): Either[E, A] = Right(a)
override def flatMap[A,B](eea: Either[E, A])(f: A => Either[E, B]) = eea match {
case Right(a) => f(a)
case Left(b) => Left(b)
}
}
def stateMonad[S] = new Monad[({type f[x] = State[S, x]})#f] {
def unit[A](a: => A): State[S, A] = State(s => (a, s))
override def flatMap[A,B](st: State[S, A])(f: A => State[S, B]): State[S, B] =
st flatMap f
}
// Monad composition
def composeM[G[_],H[_]](implicit G: Monad[G], H: Monad[H], T: Traverse[H]):
Monad[({type f[x] = G[H[x]]})#f] = new Monad[({type f[x] = G[H[x]]})#f] {
def unit[A](a: => A): G[H[A]] = G.unit(H.unit(a))
override def flatMap[A,B](mna: G[H[A]])(f: A => G[H[B]]): G[H[B]] =
G.flatMap(mna)(na => G.map(T.traverse(na)(f))(H.join))
}
}
trait Traverse[F[_]] extends Functor[F] with Foldable[F] { self =>
def traverse[M[_]:Applicative,A,B](fa: F[A])(f: A => M[B]): M[F[B]] =
sequence(map(fa)(f))
def sequence[M[_]:Applicative,A](fma: F[M[A]]): M[F[A]] =
traverse(fma)(ma => ma)
type Id[A] = A
val idMonad = new Monad[Id] {
def unit[A](a: => A) = a
override def flatMap[A,B](a: A)(f: A => B): B = f(a)
}
def map[A,B](fa: F[A])(f: A => B): F[B] =
traverse[Id, A, B](fa)(f)(idMonad)
import Applicative._
override def foldMap[A,B](as: F[A])(f: A => B)(mb: Monoid[B]): B =
traverse[({type f[x] = Const[B,x]})#f,A,Nothing](
as)(f)(monoidApplicative(mb))
def traverseS[S,A,B](fa: F[A])(f: A => State[S, B]): State[S, F[B]] =
traverse[({type f[x] = State[S, x]})#f, A, B](fa)(f)(Monad.stateMonad)
def zipWithIndex_[A](ta: F[A]): F[(A,Int)] =
traverseS(ta)((a: A) => (for {
i <- get[Int]
_ <- set(i + 1)
} yield (a, i))).run(0)._1
def toList_[A](fa: F[A]): List[A] =
traverseS(fa)((a: A) => (for {
as <- get[List[A]] // Get the current state, the accumulated list.
_ <- set(a :: as) // Add the current element and set the new list as the new state.
} yield ())).run(Nil)._2.reverse
def mapAccum[S,A,B](fa: F[A], s: S)(f: (A, S) => (B, S)): (F[B], S) =
traverseS(fa)((a: A) => (for {
s1 <- get[S]
(b, s2) = f(a, s1)
_ <- set(s2)
} yield b)).run(s)
override def toList[A](fa: F[A]): List[A] =
mapAccum(fa, List[A]())((a, s) => ((), a :: s))._2.reverse
def zipWithIndex[A](fa: F[A]): F[(A, Int)] =
mapAccum(fa, 0)((a, s) => ((a, s), s + 1))._1
def reverse[A](fa: F[A]): F[A] =
mapAccum(fa, toList(fa).reverse)((_, as) => (as.head, as.tail))._1
override def foldLeft[A,B](fa: F[A])(z: B)(f: (B, A) => B): B =
mapAccum(fa, z)((a, b) => ((), f(b, a)))._2
def zip[A,B](fa: F[A], fb: F[B]): F[(A, B)] =
(mapAccum(fa, toList(fb)) {
case (a, Nil) => sys.error("zip: Incompatible shapes.")
case (a, b :: bs) => ((a, b), bs)
})._1
def zipL[A,B](fa: F[A], fb: F[B]): F[(A, Option[B])] =
(mapAccum(fa, toList(fb)) {
case (a, Nil) => ((a, None), Nil)
case (a, b :: bs) => ((a, Some(b)), bs)
})._1
def zipR[A,B](fa: F[A], fb: F[B]): F[(Option[A], B)] =
(mapAccum(fb, toList(fa)) {
case (b, Nil) => ((None, b), Nil)
case (b, a :: as) => ((Some(a), b), as)
})._1
def fuse[M[_],N[_],A,B](fa: F[A])(f: A => M[B], g: A => N[B])
(implicit M: Applicative[M], N: Applicative[N]): (M[F[B]], N[F[B]]) =
traverse[({type f[x] = (M[x], N[x])})#f, A, B](fa)(a => (f(a), g(a)))(M product N)
def compose[G[_]](implicit G: Traverse[G]): Traverse[({type f[x] = F[G[x]]})#f] =
new Traverse[({type f[x] = F[G[x]]})#f] {
override def traverse[M[_]:Applicative,A,B](fa: F[G[A]])(f: A => M[B]) =
self.traverse(fa)((ga: G[A]) => G.traverse(ga)(f))
}
}
case class Tree[+A](head: A, tail: List[Tree[A]])
object Traverse {
val listTraverse = new Traverse[List] {
override def traverse[M[_],A,B](as: List[A])(f: A => M[B])(implicit M: Applicative[M]): M[List[B]] =
as.foldRight(M.unit(List[B]()))((a, fbs) => M.map2(f(a), fbs)(_ :: _))
}
val optionTraverse = new Traverse[Option] {
override def traverse[M[_],A,B](oa: Option[A])(f: A => M[B])(implicit M: Applicative[M]): M[Option[B]] =
oa match {
case Some(a) => M.map(f(a))(Some(_))
case None => M.unit(None)
}
}
val treeTraverse = new Traverse[Tree] {
override def traverse[M[_],A,B](ta: Tree[A])(f: A => M[B])(implicit M: Applicative[M]): M[Tree[B]] =
M.map2(f(ta.head), listTraverse.traverse(ta.tail)(a => traverse(a)(f)))(Tree(_, _))
}
// An example of a Foldable that is not a functorcase class Iteration[A](a: A, f: A => A, n: Int) {
def foldMap[B](g: A => B)(M: Monoid[B]): B = {
def iterate(n: Int, b: B, c: A): B =
if (n <= 0) b else iterate(n-1, g(c), f(a))
iterate(n, M.zero, a)
}
}
}
object Test {
def main(args: Array[String]): Unit = {
val streamApplicative = Applicative.streamApplicative
val ones = streamApplicative.unit(1)
val twos = streamApplicative.unit(2)
println(streamApplicative.map2(ones, twos)(_ -> _).take(10))
println(streamApplicative.map2(ones, twos)(_ -> _).take(10).toList)
import Applicative._
import scala.language.implicitConversions
val intMonoidApplicative = Monoid.intAddition
println(intMonoidApplicative(1)(2))
println(intMonoidApplicative.unit(8))
//通过compose得到一个产生流的流
val composedStream = streamApplicative.compose(streamApplicative)
println(composedStream.unit(1).take(4).toList)
val validationComposeStream = Applicative.validationApplicative[Exception].compose(streamApplicative)
println(validationComposeStream.unit(0))
//反过来调用,类型推导错误,汗//val streamComposeValidation= streamApplicative.compose(Applicative.validationApplicative[Exception])//println(streamApplicative.unit(0))
println(Monad.stateMonad[List[Int]].unit(5).run(Nil))
val listTraverse = Traverse.listTraverse
val li = List(1, 2, 3, 4, 5, 6, 7, 8)
val listTraverseS = listTraverse.traverseS[Int, Int, Int](li)((a: Int) => State.unit(a))
println(listTraverseS.run(0))
val zipWithIndexRes = listTraverse.zipWithIndex(li)
println(zipWithIndexRes)
val zipWithIndex_Res = listTraverse.zipWithIndex_(li)
println(zipWithIndex_Res)
val li1 = List("one", "two", "three", "four", "five", "six", "seven")
val li2 = List(11, 12, 13, 14, 15)
val zipLRes = listTraverse.zipL(li1, li2)
println(zipLRes)
val zipRRes = listTraverse.zipR(List("one", "two", "three"), li2)
println(zipRRes)
val fuse = listTraverse.fuse[({type f[x] = State[Int, x]})#f, ({type f[x] = State[Int, x]})#f, Int, Int](List(1, 2, 3, 4, 5))(
(a: Int) => State.unit(a),
(a: Int) => State.unit(2 * a))(Monad.stateMonad, Monad.stateMonad)
println(fuse._1.run(0))
println(fuse._2.run(0))
val listComposeOption = listTraverse.compose(Traverse.optionTraverse)
val liOp1 = List(Some(3), None)
val liOp2 = List(Some(3), Some(5))
val f = (a: Int) => State.unit[Int, Int]( a * a)
val listComposeOptionRes = listComposeOption.traverse[({type f[x] = State[Int, x]})#f,Int, Int](liOp1)(f)(Monad.stateMonad)
println(listComposeOptionRes.run(0))
val listComposeOptionRes2 = listComposeOption.traverse[({type f[x] = State[Int, x]})#f,Int, Int](liOp2)(f)(Monad.stateMonad)
println(listComposeOptionRes2.run(0))
val streamProduct = streamApplicative.product(streamApplicative)
println(streamProduct.unit(1))
val pow2 = (a: Int) => math.pow(a, 2)
val double = (a: Int) => 2 * a
val streamProductApplyRes = streamProduct((streamApplicative.unit(pow2), streamApplicative.unit(double)))(streamProduct.unit(3))
println(streamProductApplyRes)
}
}