我正在玩
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(1))
所以现在我有了这些东西的清单.我的目标是为posns的最小值/最大值返回一个Option [CC],如果没有低于零的值且类似于max,则我得到min为min.
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] = $anon$1@1e48d65 scala> posns.filter(_.v < 0) <^> (_.min) res0: Option[CC] = None scala> posns.filter(_.v > 0) <^> (_.max) res1: Option[CC] = Some(CC(5))
选项正是我想要的Zero类型!任何人都可以解释为什么选择是由typer选择的?我没有在任何地方宣布它!
解决方法
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(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]); }
列表@#< ^>从NonEmptyList [A] =>运行提供的函数B如果pimped列表非空,否则返回类型B的Zero .MA#min实际返回Option [B] – 它是容器的通用函数,而不是NonEmptyList的特定函数,它可以返回B .
实现这一目标的更直接方法是直接调用MA#min.遗憾的是,List已经有了一个min函数,Scala 2.8中的new函数,因此如果没有类型提示,则不会触发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中提供符号标识符的激励原因之一 – 它是命名空间的粗略形式!
附注:您可以简化CC的Order实例的实例:
implicit val CCOrder: Order[CC] = orderBy(_.v) CCOrder: scalaz.Order[CC] = scalaz.Orders$$anon$2@fc2528