2010-07-28 9 views
6

Tôi đang chơi xung quanh với ListW.<^>, định nghĩa của nó là như sau:Nhập câu hỏi suy luận bằng Scalaz.ListW. <^>

def <^>[B: Zero](f: NonEmptyList[A] => B): B = value match { 
    case Nil => ∅ 
    case h :: t => f(Scalaz.nel(h, t)) 
} 

tôi không thể tìm ra cách đi Option đang được chọn là loại Zero ví dụ này

scala> case class CC(v : Int) 
defined class CC 

scala> val posns = List(CC(2), CC(5), CC(1)) 
posns: List[CC] = List(CC(2), CC(5), CC(1)) 

Vì vậy, bây giờ tôi có một danh sách những điều này. Mục tiêu của tôi là lấy lại số Option[CC] cho tối thiểu/tối đa là posns nơi tôi nhận được None cho tối thiểu nếu không có giá trị nào dưới 0 và tương tự cho giá thầu CPC

scala> import scalaz._; import Scalaz._ 
import scalaz._ 
import Scalaz._ 

scala> implicit val CCOrder = new Order[CC] { 
     | def order(v1 : CC, v2 : CC) = orderBy((v : CC) => v.v).order(v1, v2) 
     | } 
CCOrder: java.lang.Object with scalaz.Order[CC] = [email protected] 

scala> posns.filter(_.v < 0) <^> (_.min) 
res0: Option[CC] = None 

scala> posns.filter(_.v > 0) <^> (_.max) 
res1: Option[CC] = Some(CC(5)) 

Lựa chọn là chính xác loại Zero tôi muốn! Bất cứ ai có thể giải thích làm thế nào đến Option đang được lựa chọn bởi các typer? Tôi không khai báo nó ở bất cứ đâu!

Trả lời

5

Các định nghĩa cho ListW#<^>MA#min:

sealed trait MA[M[_], A] extends PimpedType[M[A]] { 
    def min(implicit r: Foldable[M], ord: Order[A]): Option[A] = 
    foldl1((x: A, y: A) => if (x ≨ y) x else y) 
} 

sealed trait ListW[A] extends PimpedType[List[A]] { 
    def <^>[B: Zero](f: NonEmptyList[A] => B): B = value match { 
    case Nil => ∅ 
    case h :: t => f(Scalaz.nel(h, t)) 
    } 
} 

đây là các loại có liên quan suy ra, chuyển đổi ngầm, và các thông số ngầm. scalac -Xprint:typer sẽ tiết lộ điều này.

object test { 
    import scalaz._ 
    import Scalaz._ 

    case class CC(v: Int) 
    val posns = List(CC(2), CC(5), CC(1)) 
    val filtered = posns.filter(((x$1: CC) => x$1.v.<(0))) 
    val listw = Scalaz.ListTo[CC](posns.filter(((x$1: CC) => x$1.v.<(0)))) 
    listw.<^>[Option[CC]]{ 
    (x$2: scalaz.NonEmptyList[CC]) => 
     Scalaz.maImplicit[scalaz.NonEmptyList, CC](x$2).min(Foldable.NonEmptyListFoldable, CCOrder) 
    }(Zero.OptionZero[CC]); 
} 

[email protected]#<^> chạy chức năng cung cấp từ NonEmptyList[A] => B nếu danh sách pimped không bị để trống, nếu không trả về Zero cho loại B. MA#min thực sự trả lại Option[B] - đó là chức năng chung cho các vùng chứa, không phải là một hàm cụ thể cho NonEmptyList, tại đó nó có thể trả lại một B.

Cách trực tiếp hơn để thực hiện việc này là gọi trực tiếp MA#min. Thật không may, List đã có một hàm min, mới trong Scala 2.8, vì vậy quan điểm ngầm để MA không được kích hoạt mà không có một loại gợi ý:

posns.filter(_.v < 0).min 
<console>:16: error: could not find implicit value for parameter cmp: Ordering[CC] 
    posns.filter(_.v < 0).min 

(posns.filter(_.v < 0): MA[List, CC]).min 
res7: Option[CC] = None 

Đây là một trong những lý do thúc đẩy để cung cấp định danh mang tính biểu tượng trong Scalaz - nó là một dạng thô của không gian tên!

Side lưu ý: bạn có thể đơn giản hóa ví dụ bạn của Order dụ cho CC:

implicit val CCOrder: Order[CC] = orderBy(_.v) 
CCOrder: scalaz.Order[CC] = [email protected] 
+0

Khi bắt đầu, bạn cho định nghĩa của 'MA # max' thay vì' # min' MA. –

+0

Ah. Vì vậy, câu hỏi tiếp theo của tôi sẽ là - "tại sao' min' đến từ 'MA' và không phải là 'Identity'?" –

+0

@alexey: đã cập nhật. 'x.min (y)' xuất phát từ 'Identity',' xs.min' khớp với 'MA'. – retronym