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

时间:2015-08-10 02:39:33

标签: scala typeclass implicit

我正在阅读一些较旧的Scala帖子以更好地理解类型类,我跑了 横跨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]]]

复制/粘贴并在REPL中运行时,我得到这个>

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

2 个答案:

答案 0 :(得分:5)

这与Scala版本没有任何关系。如果您阅读@Philippe's answer,您会发现default方法无法在任何地方定义。这不适用于任何 Scala版本。

看起来应该是这样的:

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

答案 1 :(得分:2)

感谢Jorg的回答,与this blog post一起帮助我弄清楚这里发生了什么。希望我的额外答案能够帮助那些因此而感到困惑的人。

我对类型类的心理描述是,它们是图书馆作者灌输他/她的一种手段 具有retroactive extensibility的理想特征的图书馆。

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

我将尝试扩展Phillipe的例子,以说明我对如何理解 类库可以由库设计者使用。我对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