将属性添加到类型而不是类型实例的隐式转换

implicit conversions that add properties to a type, rather than to an instance of a type

我正在阅读一些较旧的 Scala 帖子以更好地理解类型 类,并且我 运行 across this one 这似乎很有用,但这个例子似乎已经过时了。

谁能帮我找出实现 Phillipe 意图的正确方法?这是代码

trait Default[T] { def value : T }

implicit object DefaultInt extends Default[Int] {
  def value = 42
}

implicit def listsHaveDefault[T : Default] = new Default[List[T]] {
  def value = implicitly[Default[T]].value :: Nil
}

default[List[List[Int]]]

当 copy/pasted 和 运行 在 REPL 中,我得到这个>

    scala> default[List[List[Int]]]
    <console>:18: error: not found: value default
                  default[List[List[Int]]]
                  ^

与Scala版本无关。如果您阅读 @Philippe's answer,您会注意到 default 方法根本没有在任何地方定义。这在 any Scala 版本中不起作用。

它应该看起来像这样:

def default[T: Default] = implicitly[Default[T]].value

感谢 Jorg 的回答,与 this blog post 一起帮助我弄清楚这里发生了什么。希望我的补充回答能帮助到其他对此感到困惑的人。

我对类型 类 的印象是,它们是图书馆作者灌输 his/her 的一种方式 具有 retroactive extensibility.

理想特征的库

另一方面,还有另一种临时多态性技术:implicits with wrapper classes。 当您是具有某种类型的库的 消费者 时,您将使用后一种技术 缺少您认为有用的方法。

我将尝试稍微扩展 Phillipe 的例子来说明我对如何理解 type 类 可以被库设计者使用。我对 Scala 没有那么丰富的经验......所以如果 任何人注意到我的理解不正确的地方请纠正我! ;^)

// 'Default' defines a trait that represents the ability to  manufacture
// defaults for a particular type 'T'.
//
trait Default[T] { def value : T }


// Define a default for int.. this is an object default
//
implicit object DefaultInt extends Default[Int] {
      def value = 42
}


// Define a default for Lists that contain instances of a 'T'.
// Interesting that this is method, not an object implicit definition. I
// guess that is to enable the 'on the fly' creation of default values for
// lists of any old type....  So I guess that's why we have 
// a 'method implicit' rather than an 'object implicit' definition.

implicit def listsHaveDefault[T : Default] = new Default[List[T]] {
  def value = implicitly[Default[T]].value :: Nil
}



// Here is the meat of the library... a method to make a message based of
// some arbitrary seed String, where that method is parameterized by 'T',
// a type chosen by the library user.   That 'T' can be 
// types for which implicits are already defined by the base library 
// (T = Int, and List[T]), or an implicit defined by the library user.   
//
// So the library is open for extension.
//
def makeMsg[T](msg: String)(implicit something: Default[T]) : String = {
    msg + something.value
} 

鉴于上面的代码,如果我可以为 List[List[Int]] 类型或 Int 类型创建消息

makeMsg[List[List[Int]]]("moocow-")
makeMsg[Int]("dogbox")

我得到了这个结果:

res0: String = moocow-List(List(42))
res1: String = dogbox42

如果我想覆盖给定类型的默认隐式值,我可以这样做:

makeMsg[Int]("moocow-")(something=new Object with Default[Int] { def value = 33344 }  )

我得到了这个结果:

res3: String = moocow-33344