2012-06-19 9 views
19

Was ist Comonad, wenn es möglich ist, in Scala-Syntax zu beschreiben. Ich fand scalaz Bibliothek Implementierung, aber es ist nicht klar, wo es nützlich sein kann.Comonad Beispiel in Scala

+1

Siehe auch: [Was ist die Comonad-Klasse in Haskell] (http://stackoverflow.com/questions/8428554/what-is-the-comonad-typeclass-in-haskell). Scalaz versucht im Allgemeinen, Dinge wie Haskell-ish als möglich zu machen, daher können diese Blogposts helfen. –

+0

Siehe auch: recent reddit post at/r/haskell [Eine Notation für Comonads] ​​(http://www.reddit.com/r/haskell/comments/v6ik6/a_notation_for_comonads_orchard_mycroft_pdf/) –

Antwort

12

Nun, Monaden können Sie Werte, um sie hinzuzufügen, so dass sie von einem nicht-Monade Monade auf einer Berechnung basiert ändern. Comonads erlauben Ihnen, Werte von ihnen zu extrahieren und sie basierend auf einer Berechnung von einem Comonad zu einem Nicht-Comonad zu ändern.

Die natürliche Intuition ist, dass sie werden in der Regel angezeigt, in dem Sie ein CM [A] haben und A.

Siehe this sehr interessanten Beitrag zu extrahieren, die ein bisschen lässig auf comonads berührt, aber, mir bei zumindest, sie sehr klar zu machen.

+0

"Die natürliche Intuition ist, dass sie normalerweise erscheinen, wo Sie ein CM [A] haben und A. extrahieren möchten." Das ist 'Copointed' /' Copure'. Fügen Sie dazu 'extract' hinzu (' W [A] => (W [A] => B) => W [B] ') oder' cojoin' ('W [A] => W [W [A]] '), und du bekommst' Comonad'. – missingfaktor

+0

@missingfaktor Ich definiere sie nicht - ich nehme an, Stas hat die Definition schon gesehen. Ich sage Comonaden werden normalerweise in solchen Situationen gefunden. –

7

Was folgt, ist eine wörtliche Übersetzung von Code aus this Blogpost.

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) 

Ausgang:

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

Import für 'Comonad' fehlt. '= >>' und '|>' sind auch nicht definiert. – EnverOsmanov

+0

@EnverOsmanov, dieser Beitrag stammt aus einer Zeit, als ich nicht erkannte, wie wichtig es ist, Importe in Code-Snippets einzubeziehen. :-) Wie auch immer, Scalaz hat sich seitdem enorm verändert und die Pakete haben mehrere Reorganisationsrunden durchlaufen. Ich würde es begrüßen, wenn du diesen Beitrag nach neuen Scalaz (oder Katzen, wenn das dein Gift ist) aktualisieren könnte. – missingfaktor