简体   繁体   English

使用Scalaz.ListW。<^>键入推断问题

[英]Type inference question using Scalaz.ListW.<^>

I was playing around with ListW.<^> , the definition of which is as follows: 我正在玩ListW.<^> ,其定义如下:

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

I cannot figure out how come Option is being chosen as the Zero type for this example 我无法弄清楚如何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))

So now I have a List of these things. 所以现在我有了这些东西的清单。 My goal is to get back an Option[CC] for the min/max of posns where I get a None for min if there are no values below zero and similar for max. 我的目标是要取回一个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] = $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))

Option was exactly the Zero type I wanted! 选项正是我想要的Zero类型! Can anyone explain how come Option is being chosen by the typer? 任何人都可以解释为什么Option是由typer选择的? I don't declare it anywhere ! 我没有在任何地方宣布它!

The definitions for ListW#<^> and MA#min : 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))
  }
}

Here are the relevant inferred types, implicit conversion, and implicit parameters. 以下是相关的推断类型,隐式转换和隐式参数。 scalac -Xprint:typer will reveal this. 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@#<^> runs the provided function from NonEmptyList[A] => B if the pimped list is non-empty, otherwise returns the Zero for type B . 如果pimped列表非空,则List@#<^>运行NonEmptyList[A] => B提供的函数,否则返回类型BZero MA#min actually returns Option[B] -- it is a general function for containers, not a specific one for NonEmptyList , where it could return a B . MA#min实际返回Option[B] - 它是容器的通用函数,而不是NonEmptyList的特定函数,它可以返回B

A more direct way to achieve this is to call MA#min directly. 实现这一目标的更直接方法是直接调用MA#min Unfortunately, List already has a min function, new in Scala 2.8, so the implicit view to MA is not triggered without a type hint: 遗憾的是, 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

This is one of the motivating reasons to provide symbolic identifiers in Scalaz -- it is a crude form of namespacing! 这是在Scalaz中提供符号标识符的激励原因之一 - 它是命名空间的粗略形式!

Side note: you can simplify your instance of the Order instance for CC : 附注:您可以简化CCOrder实例的实例:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM