2010-04-01 14 views
17

Câu hỏi này không có nghĩa là mồi lửa! Có thể thấy rõ ràng, gần đây tôi đã xem xét Scalaz. Tôi đang cố gắng hiểu lý do tại sao Tôi cần một số chức năng mà thư viện cung cấp. Dưới đây là một cái gì đó:Scalaz: yêu cầu sử dụng vỏ bọc cho thành phần Cokleisli

import scalaz._ 
import Scalaz._ 
type NEL[A] = NonEmptyList[A] 
val NEL = NonEmptyList 

tôi đặt một số báo cáo println trong các chức năng của tôi để xem những gì đang xảy ra (sang một bên: điều gì sẽ Tôi đã làm nếu tôi đã cố gắng để tránh tác dụng phụ như thế?). chức năng của tôi là:

val f: NEL[Int] => String = (l: NEL[Int]) => {println("f: " + l); l.toString |+| "X" } 
val g: NEL[String] => BigInt = (l: NEL[String]) => {println("g: " + l); BigInt(l.map(_.length).sum) } 

Sau đó, tôi kết hợp chúng thông qua một cokleisli và vượt qua trong một NEL[Int]

val k = cokleisli(f) =>= cokleisli(g) 
println("RES: " + k(NEL(1, 2, 3))) 

gì in này?

f: NonEmptyList(1, 2, 3) 
f: NonEmptyList(2, 3) 
f: NonEmptyList(3) 
g: NonEmptyList(NonEmptyList(1, 2, 3)X, NonEmptyList(2, 3)X, NonEmptyList(3)X) 
RES: 57 

Giá trị RES là số ký tự của phần tử (Chuỗi) trong NEL cuối cùng. Hai điều xảy ra với tôi:

  1. Làm cách nào để biết rằng NEL của tôi sẽ bị giảm theo cách này từ chữ ký của phương thức liên quan? (Tôi không mong đợi kết quả ở tất cả)
  2. Điểm này là gì? Trường hợp sử dụng hợp lý đơn giản và dễ theo dõi có thể được chưng cất cho tôi không?

Câu hỏi này là một lời biện hộ mỏng che kín mặt-đối với một số người đáng yêu như retronym để giải thích như thế nào thư viện mạnh mẽ này thực sự hoạt động.

Trả lời

18

Để hiểu kết quả, bạn cần hiểu trường hợp Comonad[NonEmptyList]. Comonad[W] về cơ bản cung cấp ba chức năng (giao diện thực tế trong Scalaz là một chút khác nhau, nhưng điều này giúp với lời giải thích):

map: (A => B) => W[A] => W[B] 
copure: W[A] => A 
cojoin: W[A] => W[W[A]] 

Vì vậy, Comonad cung cấp một giao diện cho một số thùng chứa W rằng có một yếu tố "đầu" phân biệt (copure) và một cách để lộ cấu trúc bên trong của thùng chứa sao cho chúng tôi lấy một thùng chứa trên mỗi phần tử (cojoin), mỗi phần có một phần tử đã cho ở đầu.

Cách thực hiện điều này cho NonEmptyListcopure trả về đầu danh sách và cojoin trả về danh sách danh sách ở đầu và tất cả đuôi của danh sách này ở đuôi.

Ví dụ (Tôi đang rút ngắn NonEmptyList để Nel):

Nel(1,2,3).copure = 1 
Nel(1,2,3).cojoin = Nel(Nel(1,2,3),Nel(2,3),Nel(3)) 

Các =>= chức năng là thành phần coKleisli. Bạn sẽ soạn hai chức năng như thế nào f: W[A] => Bg: W[B] => C, không biết gì về chúng ngoài số WComonad? Kiểu đầu vào của f và loại đầu ra của g không tương thích.Tuy nhiên, bạn có thể map(f) để nhận W[W[A]] => W[B] và sau đó soạn thư đó với g. Bây giờ, với một số W[A], bạn có thể cojoin để lấy số W[W[A]] để nạp vào hàm đó. Vì vậy, thành phần hợp lý chỉ là một chức năng k nào sau đây:

k(x) = g(x.cojoin.map(f)) 

Vì vậy cho danh sách không rỗng của bạn:

g(Nel(1,2,3).cojoin.map(f)) 
= g(Nel(Nel(1,2,3),Nel(2,3),Nel(3)).map(f)) 
= g(Nel("Nel(1,2,3)X","Nel(2,3)X","Nel(3)X")) 
= BigInt(Nel("Nel(1,2,3)X","Nel(2,3)X","Nel(3)X").map(_.length).sum) 
= BigInt(Nel(11,9,7).sum) 
= 27 
+0

Cảm ơn câu trả lời này - Tôi đã chấp nhận * từ viết tắt * vì anh ấy đã trả lời yêu cầu cho một ca sử dụng nhưng trường hợp này vẫn tuyệt vời! –

+0

Không đổ mồ hôi, tôi đã chỉnh sửa câu trả lời của từ viết tắt để thêm ví dụ về thành phần cokleisli. – Apocalisp

+0

Tôi tin rằng bạn "bạn có thể' ánh xạ (f) 'để có được' W [W [A]] => W [B] '", than ôi, tôi không có quyền chỉnh sửa. –

9

Cojoin cũng được định nghĩa cho scalaz.Treescalaz.TreeLoc. Điều này có thể là exploited để tìm một luồng của tất cả các đường dẫn từ gốc cây đến từng nút lá.

def leafPaths[T](tree: Tree[T]): Stream[Stream[T]] 
    = tree.loc.cojoin.toTree.flatten.filter(_.isLeaf).map(_.path) 

Sử dụng phần mũi tên coKleisli, chúng ta có thể làm được điều này, ví dụ:

def leafDist[A] = (cokleisli(leafPaths[A]) &&& cokleisli(_.rootLabel)) 
    =>= (_.map(s => (s._2, s._1.map(_.length).max))) 

leafDist mất một Tree và trả về một bản sao của nó với mỗi nút chú thích với khoảng cách tối đa của nó từ một chiếc lá.

Các vấn đề liên quan