2012-06-19 21 views
19

Comonad là gì, nếu có thể mô tả trong cú pháp Scala. Tôi đã tìm thấy scalaz triển khai thư viện, nhưng không rõ nơi nó có thể hữu ích.Ví dụ Comonad trong Scala

+1

Xem thêm: [Comonad typeclass trong Haskell] là gì (http://stackoverflow.com/questions/8428554/what-is-the-comonad-typeclass-in-haskell). Scalaz thường cố gắng làm mọi thứ như Haskell-ish nhất có thể, vì vậy những bài đăng trên blog này có thể hữu ích. –

+0

Cũng xem thêm: bài đăng reddit gần đây tại/r/haskell [Một ký hiệu cho Comonads] ​​(http://www.reddit.com/r/haskell/comments/v6ik6/a_notation_for_comonads_orchard_mycroft_pdf/) –

Trả lời

12

Vâng, monads cho phép bạn thêm giá trị cho họ, thay đổi họ dựa trên tính toán từ một tổ chức phi đơn nguyên để một đơn nguyên. Comonads cho phép bạn trích xuất các giá trị từ chúng, và thay đổi chúng dựa trên một tính toán từ một comonad đến một non-comonad.

Trực giác tự nhiên là họ sẽ thường xuất hiện nơi bạn có một CM [A] và muốn trích xuất A.

Xem this bài rất thú vị mà chạm vào comonads một chút tình cờ, nhưng, với tôi tại ít nhất, làm cho chúng rất rõ ràng.

+0

"Trực giác tự nhiên là chúng thường xuất hiện khi bạn có CM [A] và muốn trích xuất A." Đó là 'Copointed' /' Copure'. Thêm vào đó 'extract' (' W [A] => (W [A] => B) => W [B] ') hoặc' cojoin' ('W [A] => W [W [A]] '), và bạn nhận được' Comonad'. – missingfaktor

+0

@missingfaktor Tôi không định nghĩa chúng - Tôi cho rằng Stas đã thấy định nghĩa rồi. Tôi đang nói comonads thường sẽ được tìm thấy trong các tình huống như thế này. –

7

Nội dung sau là bản dịch chữ của mã từ this bài đăng trên 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) 

Output:

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

Nhập cho 'Comonad' bị thiếu. '= >>' và '|>' cũng không được định nghĩa. – EnverOsmanov

+0

@EnverOsmanov, bài đăng này là từ thời điểm tôi không nhận ra tầm quan trọng của việc bao gồm nhập khẩu trong đoạn mã. :-) Dù sao, Scalaz đã thay đổi rất nhiều kể từ đó, và các gói đã thấy nhiều vòng tổ chức lại. Tôi sẽ đánh giá cao nếu bạn có thể cập nhật bài đăng này theo Scalaz mới (hoặc Mèo, nếu đó là chất độc của bạn). – missingfaktor