2012-06-19 20 views
19

Qué es Comonad, si es posible describirlo en la sintaxis de Scala. Encontré la implementación de la biblioteca scalaz, pero no está claro dónde puede ser útil.Ejemplo de Comonad en Scala

+1

Vea también: [¿Qué es la clase de tipo Comonad en Haskell] (http://stackoverflow.com/questions/8428554/what-is-the-comonad-typeclass-in-haskell). Scalaz generalmente intenta hacer las cosas como Haskell-ish como sea posible, por lo que esas publicaciones de blog pueden ayudar. –

+0

Vea también: publicación reciente de reddit en/r/haskell [Una notación para Comonads] ​​(http://www.reddit.com/r/haskell/comments/v6ik6/a_notation_for_comonads_orchard_mycroft_pdf/) –

Respuesta

12

Bueno, mónadas permiten añadir valores a ellos, los cambia en base a un cálculo de un no-mónada a una mónada. Comonads le permite extraer valores de ellos y cambiarlos en función de un cálculo de comonad a non-comonad.

La intuición natural es que por lo general va aparecerá donde usted tiene un CM [A] y desea extraer A.

Ver this post muy interesante que toca comonads un poco por casualidad, pero, para mí en al menos, haciéndolos muy claros.

+0

"La intuición natural es que generalmente aparecerán donde tengas un CM [A] y quieras extraer A". Eso es 'Copointed' /' Copure'. Añádalo 'extract' (' W [A] => (W [A] => B) => W [B] ') o' cojoin' ('W [A] => W [W [A]] '), y obtienes' Comonad'. – missingfaktor

+0

@missingfaktor No los estoy definiendo, supongo que Stas ya ha visto la definición. Estoy diciendo que las comonads generalmente se encontrarán en situaciones como esta. –

7

Lo que sigue es una traducción literal del código de this publicación en el blog.

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) 

Salida:

| | | | | | | | | | | | | | | | | | | |#| | | | | | | | | | | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#|#| | | | | | | | | | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#| |#| | | | | | | | | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#|#|#|#| | | | | | | | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#| | | |#| | | | | | | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#|#| | |#|#| | | | | | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#| |#| |#| |#| | | | | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#|#|#|#|#|#|#|#| | | | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#| | | | | | | |#| | | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#|#| | | | | | |#|#| | | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#| |#| | | | | |#| |#| | | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#|#|#|#| | | | |#|#|#|#| | | | | | | | 
| | | | | | | | | | | | | | | | | | | |#| | | |#| | | |#| | | |#| | | | | | | 
| | | | | | | | | | | | | | | | | | | |#|#| | |#|#| | |#|#| | |#|#| | | | | | 
| | | | | | | | | | | | | | | | | | | |#| |#| |#| |#| |#| |#| |#| |#| | | | | 
| | | | | | | | | | | | | | | | | | | |#|#|#|#|#|#|#|#|#|#|#|#|#|#|#|#| | | | 
| | | | | | | | | | | | | | | | | | | |#| | | | | | | | | | | | | | | |#| | | 
| | | | | | | | | | | | | | | | | | | |#|#| | | | | | | | | | | | | | |#|#| | 
| | | | | | | | | | | | | | | | | | | |#| |#| | | | | | | | | | | | | |#| |#| 
| | | | | | | | | | | | | | | | | | | |#|#|#|#| | | | | | | | | | | | |#|#|#|# 
+0

Falta la importación de 'Comonad'. '= >>' y '|>' no están definidos también. – EnverOsmanov

+0

@EnverOsmanov, esta publicación es de una época en la que no me daba cuenta de la importancia de incluir importaciones en los fragmentos de código. :-) De todos modos, Scalaz ha cambiado enormemente desde entonces, y los paquetes han visto múltiples rondas de reorganización. Le agradecería si pudiera actualizar esta publicación según el nuevo Scalaz (o los gatos, si ese es su veneno). – missingfaktor

Cuestiones relacionadas