Введите вопрос вывода, используя Scalaz.ListW. <^> - PullRequest
6 голосов
/ 28 июля 2010

Я играл с 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 для мин, если нет значений ниже нуля и аналогично для макс.был точно Zero тип, который я хотел!Кто-нибудь может объяснить, почему типер выбирает Option?Я не объявляю это нигде !

1 Ответ

5 голосов
/ 28 июля 2010

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

List@#<^> запускает предоставленную функцию из 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 - это грубая форма пространства имен!

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

implicit val CCOrder: Order[CC] = orderBy(_.v)
CCOrder: scalaz.Order[CC] = scalaz.Orders$$anon$2@fc2528
...