是否可以使用类型类来实现特征?
Is it possible to use a typeclass to implement a trait?
我有一种情况想要实现给定的特征(下例中的CanBeString
)。我希望可以选择使用新创建的案例 class(下面示例中的 NewImplementation
)来实现该特征,或者通过向某些预先存在的类型添加功能来实现它(只是 Int
在下面的示例中),通过使用类型 class。下面可能是最好的说明:
package example
// typeclass
trait ConvertsToString[A] {
def asString(value: A): String
}
// the trait I would like the typeclass to implement
trait CanBeString {
def asString: String
}
// this implementation approach taken from the scala with cats book
object ConvertsToStringInstances {
implicit val intConvertsToString: ConvertsToString[Int] =
new ConvertsToString[Int] {
def asString(value: Int): String = s"${value}"
}
}
object ConvertsToStringSyntax {
implicit class ConvertsToStringOps[A](value: A) {
def asString(implicit c: ConvertsToString[A]): String = c.asString(value)
}
}
object Test {
import ConvertsToStringInstances._
import ConvertsToStringSyntax._
def testAsFunc(c: CanBeString): String = c.asString
case class NewImplementation (f: Double) extends CanBeString {
def asString = s"{f}"
}
println(testAsFunc(NewImplementation(1.002))) // this works fine!
println(testAsFunc(1)) // this sadly does not.
}
这可能吗?我最近才发现 typeclasses 的主题,所以我知道我在这里要求的可能是可行的,但不明智 - 如果是这样,请插话让我知道更好的成语可能是什么是。
在此先感谢,之后也感谢!
例如,您可以有两个重载版本的 testAsFunc
(OOP-style 和 typeclass-style)
object Test {
...
def testAsFunc(c: CanBeString): String = c.asString
def testAsFunc[C: ConvertsToString](c: C): String = c.asString
println(testAsFunc(NewImplementation(1.002))) // {f}
println(testAsFunc(1)) // 1
}
或者,如果您希望拥有唯一的 testAsFunc
,那么您可以添加 class 类型的实例,以实现要实现的特征的子类型
object ConvertsToStringInstances {
implicit val intConvertsToString: ConvertsToString[Int] = ...
implicit def canBeStringSubtypeConvertsToString[A <: CanBeString]: ConvertsToString[A] =
new ConvertsToString[A] {
override def asString(value: A): String = value.asString
}
}
object Test {
...
def testAsFunc[C: ConvertsToString](c: C): String = c.asString
println(testAsFunc(NewImplementation(1.002))) // {f}
println(testAsFunc(1)) // 1
}
请注意,如果 c
同时存在 OOP-ish c.asString
和 extension-method c.asString
,那么实际上只会调用第一个。
我有一种情况想要实现给定的特征(下例中的CanBeString
)。我希望可以选择使用新创建的案例 class(下面示例中的 NewImplementation
)来实现该特征,或者通过向某些预先存在的类型添加功能来实现它(只是 Int
在下面的示例中),通过使用类型 class。下面可能是最好的说明:
package example
// typeclass
trait ConvertsToString[A] {
def asString(value: A): String
}
// the trait I would like the typeclass to implement
trait CanBeString {
def asString: String
}
// this implementation approach taken from the scala with cats book
object ConvertsToStringInstances {
implicit val intConvertsToString: ConvertsToString[Int] =
new ConvertsToString[Int] {
def asString(value: Int): String = s"${value}"
}
}
object ConvertsToStringSyntax {
implicit class ConvertsToStringOps[A](value: A) {
def asString(implicit c: ConvertsToString[A]): String = c.asString(value)
}
}
object Test {
import ConvertsToStringInstances._
import ConvertsToStringSyntax._
def testAsFunc(c: CanBeString): String = c.asString
case class NewImplementation (f: Double) extends CanBeString {
def asString = s"{f}"
}
println(testAsFunc(NewImplementation(1.002))) // this works fine!
println(testAsFunc(1)) // this sadly does not.
}
这可能吗?我最近才发现 typeclasses 的主题,所以我知道我在这里要求的可能是可行的,但不明智 - 如果是这样,请插话让我知道更好的成语可能是什么是。
在此先感谢,之后也感谢!
例如,您可以有两个重载版本的 testAsFunc
(OOP-style 和 typeclass-style)
object Test {
...
def testAsFunc(c: CanBeString): String = c.asString
def testAsFunc[C: ConvertsToString](c: C): String = c.asString
println(testAsFunc(NewImplementation(1.002))) // {f}
println(testAsFunc(1)) // 1
}
或者,如果您希望拥有唯一的 testAsFunc
,那么您可以添加 class 类型的实例,以实现要实现的特征的子类型
object ConvertsToStringInstances {
implicit val intConvertsToString: ConvertsToString[Int] = ...
implicit def canBeStringSubtypeConvertsToString[A <: CanBeString]: ConvertsToString[A] =
new ConvertsToString[A] {
override def asString(value: A): String = value.asString
}
}
object Test {
...
def testAsFunc[C: ConvertsToString](c: C): String = c.asString
println(testAsFunc(NewImplementation(1.002))) // {f}
println(testAsFunc(1)) // 1
}
请注意,如果 c
同时存在 OOP-ish c.asString
和 extension-method c.asString
,那么实际上只会调用第一个。