2010-07-28 2 views
6

Я играл вокруг с ListW.<^>, определение которого выглядит следующим образом:Тип вопрос вопрос используя Scalaz.ListW. <^>

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

Я не могу понять, как же Option в настоящее время выбран в качестве Zero типа для этого примера

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

Так теперь у меня есть список этих вещей. Моя цель - вернуть Option[CC] за минимальный/максимальный posns, где я получаю None за мин, если нет значений ниже нуля и аналогичных для макс.

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

Вариант был точно тип Zero я хотел! Может ли кто-нибудь объяснить, как получается Option? Я не объявляю его в любом месте!

ответ

5

Определения 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)) 
    } 
} 

Вот соответствующие выведенные типы, неявное преобразование и неявные параметры. scalac -Xprint:typer покажет это.

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]#<^> работает прилагаемую функцию из NonEmptyList[A] => B если развалюха список не пуст, в противном случае возвращает Zero для типа B. MA#min фактически возвращает Option[B] - это общая функция для контейнеров, а не для NonEmptyList, где она может вернуть B.

Более прямой способ достичь этого - позвонить по телефону MA#min напрямую. К сожалению, List уже имеет min функцию, новую в Scala 2.8, поэтому неявный вид на MA не запускается без намека типа:

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 

Это одна из мотивирующих причин, чтобы обеспечить символьные идентификаторы в Scalaz - это грубая форма пространства имен!

Side Примечание: вы можете упростить экземпляр экземпляра Order для CC:

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

В начале, вы даете определение 'MA # max' вместо' MA # min'. –

+0

Ах. Поэтому мой следующий вопрос будет: «Почему« мин »исходит от« MA », а не« Identity »?» –

+0

@alexey: обновлено. 'x.min (y)' происходит от 'Identity',' xs.min' соответствует 'MA'. – retronym

Смежные вопросы