2010-07-28 15 views
6

Grałem około z ListW.<^> definicja brzmi następująco:Wpisz pytanie dotyczące wnioskowania za pomocą Scalaz.ListW. <^>

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

nie mogę dowiedzieć się, jak to się stało Option jest wybrany jako typ Zero dla tego przykładu

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)) 

So teraz mam listę tych rzeczy. Moim celem jest odzyskanie Option[CC] dla min/max posns, gdzie otrzymam None dla min, jeśli nie ma wartości poniżej zera i podobnie dla max.

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)) 

opcja została dokładnieZero typ chciałem! Czy ktoś może wyjaśnić, w jaki sposób typer wybiera tyranę? Nie deklaruję tego jako w dowolnym miejscu!

Odpowiedz

5

Definicje ListW#<^> i 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)) 
    } 
} 

Oto odpowiednie typy wywiedzione niejawna konwersja i parametry ukryte. scalac -Xprint:typer ujawni to.

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]#<^> uruchamia podaną funkcję od NonEmptyList[A] => B jeśli lista pimped nie jest pusty, w przeciwnym razie zwraca Zero na typ B. MA#min faktycznie zwraca Option[B] - jest to ogólna funkcja dla kontenerów, a nie specyficzna dla NonEmptyList, gdzie może zwrócić B.

Bardziej bezpośrednim sposobem osiągnięcia tego jest bezpośrednie wywołanie MA#min. Niestety, List ma już min nową funkcję, w Scala 2.8, więc niejawna widok na MA nie jest wyzwalany bez cienia typu:

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 

Jest to jeden z powodów motywujących do zapewnienia identyfikatory symboliczne w Scalaz - jest to prymitywna forma wyświetlania nazw!

Side Uwaga: Można uprościć swoje wystąpienie instancji Order dla CC:

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

Na początku podać definicję 'MA # max' zamiast' MA # min'. –

+0

Ah. Moje następne pytanie brzmi: "dlaczego" min "pochodzi od" MA ", a nie" Tożsamości "?" –

+0

@alexey: updated. 'x.min (y)' pochodzi od 'Identity',' xs.min' pasuje do 'MA'. – retronym

Powiązane problemy