将属性添加到类型而不是类型实例的隐式转换
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
我正在阅读一些较旧的 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