@MiloXia
2016-01-13T14:48:10.000000Z
字数 2493
阅读 1744
scala
函数式编程
逆Monad, 定义:
//A comonad is the same thing as a monad, only backwards
trait Comonad[W[_]] extends Functor[W] {
def counit[A](w: W[A]): A //又名extract
def duplicate[A](wa: W[A]): W[W[A]]
}
是flatMap的逆向
(W[A] -> B) -> W[A] -> W[B]
//参数与flatMap是反的,接W[A] -> A的函数,comonads的组合又叫coKleisli,逆Kleisli
def extend[B](f: Coreader[R,A] => B): Coreader[R,B] =
duplicate map f
等价于Id Monad
case class Id[A](a: A) {
def map[B](f: A => B): Id[B] = Id(f(a))
def counit: A = a
def duplicate: Id[Id[A]] = Id(this)
}
语义:当R准备好时(最后调用run传入),从R中读取出A
composition的语义:只能看到部分操作的结构A,用于后续的(map/flatMap)操作
case class Reader[R,A](run: R => A)
def ask[R]: Reader[R,R] = Reader(r => r) //unit
def join[R,A](r: Reader[R,Reader[R,A]]) =
Reader((c:R) => r.run(c).run(c))
语义:
we don’t have to pretend to have an R value. It’s just right there and we can look at it.
不需要提供(也就是run方法)R一开始就提供好了,直接取出值
composition的语义:获得全部的上下文W[A],用于后续的(extend)操作
The name extend refers to the fact that it takes a “local” computation that operates on some structure and “extends” that to a “global” computation that operates on all substructures of the larger structure.
case class Coreader[R,A](extract: A, ask: R) {
def map[B](f: A => B): Coreader[R,B] = Coreader(f(extract), ask)
def duplicate: Coreader[R, Coreader[R, A]] =
Coreader(this, ask)
def extend[B](f: Coreader[R,A] => B): Coreader[R,B] =
duplicate map f
}
def coreaderComonad[R]: Comonad[Coreader[R,?]] =
new Comonad[Coreader[R,?]] {
def map[A,B](c: Coreader[R,A])(f: A => B) = c map f
def counit[A](c: Coreader[R,A]) = c.extract
def duplicate(c: Coreader[R,A]) = c.duplicate
}
语义:往W中append A (W已经准备好,不需要run方法)
composition的语义:只能看到部分操作的结构W,用于后续的(map/flatMap)操作
case class Writer[W,A](value: A, log: W)
def tell[W,A](w: W): Writer[W,Unit] = Writer((), w)
def join[W:Monoid,A](w: Writer[W,Writer[W,A]]) =
Writer(w.value.value, Monoid[W].append(w.log, w.value.log))
def unit[W:Monoid,A](a: A) = Writer(a, Monoid[W].zero)
语义:
But instead of keeping the log always available to be appended to, it uses the same trick as the reader monad by building up an operation that gets executed once a log becomes available
当W准备好时(最后调用tell传入),从W中写入(看duplicate方法)
composition的语义:获得全部的上下文W[A],用于后续的(extend)操作
case class Cowriter[W:Monoid,A](tell: W => A) {
def map[B](f: A => B): Cowriter[W,B] = Cowriter(tell andThen f)
def extract = tell(Monoid[W].zero)
def duplicate: Cowriter[W, Cowriter[W, A]] =
Cowriter(w1 => Cowriter(w2 => tell(Monoid[W].append(w1, w2))))
def extend[B](f: Cowriter[W,A] => B): Cowriter[W,B] =
duplicate map f
}
语义上Comonad与Monad是逆反的