什么是 Comonad,如果可以用 Scala 语法描述的话。我找到了 scalaz库实现,但不清楚它在哪里有用。
问问题
2747 次
3 回答
12
好吧,monad 允许您向它们添加值,根据计算将它们从非 monad 更改为 monad。Comonads 允许您从中提取值,并根据计算将它们从comonad 更改为非comonad。
自然的直觉是,它们通常会出现在您有 CM[A] 并想要提取 A 的地方。
看到这个非常有趣的帖子,它有点随意地触及了共生词,但是,至少对我来说,让它们非常清楚。
于 2012-06-19T23:04:33.887 回答
7
以下是此博客文章中代码的字面翻译。
case class U[X](left: Stream[X], center: X, right: Stream[X]) {
def shiftRight = this match {
case U(a, b, c #:: cs) => U(b #:: a, c, cs)
}
def shiftLeft = this match {
case U(a #:: as, b, c) => U(as, a, b #:: c)
}
}
// Not necessary, as Comonad also has fmap.
/*
implicit object uFunctor extends Functor[U] {
def fmap[A, B](x: U[A], f: A => B): U[B] = U(x.left.map(f), f(x.center), x.right.map(f))
}
*/
implicit object uComonad extends Comonad[U] {
def copure[A](u: U[A]): A = u.center
def cojoin[A](a: U[A]): U[U[A]] = U(Stream.iterate(a)(_.shiftLeft).tail, a, Stream.iterate(a)(_.shiftRight).tail)
def fmap[A, B](x: U[A], f: A => B): U[B] = U(x.left.map(f), x.center |> f, x.right.map(f))
}
def rule(u: U[Boolean]) = u match {
case U(a #:: _, b, c #:: _) => !(a && b && !c || (a == b))
}
def shift[A](i: Int, u: U[A]) = {
Stream.iterate(u)(x => if (i < 0) x.shiftLeft else x.shiftRight).apply(i.abs)
}
def half[A](u: U[A]) = u match {
case U(_, b, c) => Stream(b) ++ c
}
def toList[A](i: Int, j: Int, u: U[A]) = half(shift(i, u)).take(j - i)
val u = U(Stream continually false, true, Stream continually false)
val s = Stream.iterate(u)(_ =>> rule)
val s0 = s.map(r => toList(-20, 20, r).map(x => if(x) '#' else ' '))
val s1 = s.map(r => toList(-20, 20, r).map(x => if(x) '#' else ' ').mkString("|")).take(20).force.mkString("\n")
println(s1)
输出:
| | | | | | | | | | | | | | | | | | | |#| | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#|#| | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#| |#| | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#|#|#|#| | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#| | | |#| | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#|#| | |#|#| | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#| |#| |#| |#| | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#|#|#|#|#|#|#|#| | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#| | | | | | | |#| | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#|#| | | | | | |#|#| | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#| |#| | | | | |#| |#| | | | | | | | |
| | | | | | | | | | | | | | | | | | | |#|#|#|#| | | | |#|#|#|#| | | | | | | |
| | | | | | | | | | | | | | | | | | | |#| | | |#| | | |#| | | |#| | | | | | |
| | | | | | | | | | | | | | | | | | | |#|#| | |#|#| | |#|#| | |#|#| | | | | |
| | | | | | | | | | | | | | | | | | | |#| |#| |#| |#| |#| |#| |#| |#| | | | |
| | | | | | | | | | | | | | | | | | | |#|#|#|#|#|#|#|#|#|#|#|#|#|#|#|#| | | |
| | | | | | | | | | | | | | | | | | | |#| | | | | | | | | | | | | | | |#| | |
| | | | | | | | | | | | | | | | | | | |#|#| | | | | | | | | | | | | | |#|#| |
| | | | | | | | | | | | | | | | | | | |#| |#| | | | | | | | | | | | | |#| |#|
| | | | | | | | | | | | | | | | | | | |#|#|#|#| | | | | | | | | | | | |#|#|#|#
于 2012-06-19T22:13:32.253 回答
1
scalaz库提供了一个ComonadStore
扩展Comonad
. 它是这样定义的:
trait ComonadStore[F[_], S] extends Comonad[F] { self =>
def pos[A](w: F[A]): S
def peek[A](s: S, w: F[A]): A
def peeks[A](s: S => S, w: F[A]): A =
peek(s(pos(w)), w)
def seek[A](s: S, w: F[A]): F[A] =
peek(s, cojoin(w))
def seeks[A](s: S => S, w: F[A]): F[A] =
peeks(s, cojoin(w))
def experiment[G[_], A](s: S => G[S], w: F[A])(implicit FG: Functor[G]): G[A] =
FG.map(s(pos(w)))(peek(_, w))
}
并且 a Store
(类似于(S => A, S)
)具有 的实例Comonad
。你可以看看这个问题,它更具体地解释了它的含义。
你也有Coreader
andCowriter
Comonads
是 and 的对偶Reader
,Writer
Monads
这里有一篇很棒的博客文章,在 Scala 中讨论了它。
于 2019-01-11T13:29:57.960 回答