我正在阅读一些较旧的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]]]
^
答案 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