Scala:返回未知类型的函数
Scala: Function returning an unknown type
如果我想创建一个 add 方法来添加两种不同类型的值,例如:
add[T,S](op1: T, op2: S): ? = ...
我能想到的最值得注意的例子是基本数字类型。如果我添加一个 Byte 和一个 Int,那么它将 return 一个 Int。如果添加两个字节,它可能 return 一个 Int 取决于字节的 -127 到 128 限制是否被打破。
此外,如果我想创建具有相同特征的 classes,我希望它也能这样做。
一个可能的解决方案是让 class 扩展相同的特征或 class。但是对于 Scala 原始类型的示例,这并不适用,因为 Int、Double、Float、Byte 除了 Any 之外没有共同的祖先。
我还查看了 Numeric[T] 特征,但在添加不同的基本类型时这似乎没有帮助。
谢谢
凯
这是某种联合类型类的主要示例。
首先定义一个类似 Numeric[T]
的东西,但为了可添加性:
trait Addable[T, S] {
type Result
def add(x: T, y: S): Result
}
现在,定义您的 add
函数:
def add[T,S](op1: T, op2: S)(implicit op: Addable[T, S]): op.Result =
op.add(op1, op2)
您剩下要做的就是为 Addable
:
创建隐式实例
// Put them in the companion object, so the implicits are available
// without explicit import
object Addable {
// Make any numeric addable
implicit def numericAddable[T : Numeric]: Addable[T, T] = {
new Addable[T, T] {
type Result = T
def add(x: T, y: T): T = {
val op = implicitly[Numeric[T]]
op.plus(x, y)
}
}
}
}
但您现在也可以定义自己的 类 并定义(非对称)加法能力:
case class A(x: Int)
case class B(x: Int)
case class C(x: Int)
implicit object AddABC extends Addable[A,B] {
type Result = C
def add(x: A, y: B): C = C(x.x + y.x)
}
这将允许您编写:
add(A(1), B(2))
但是,其中任何一个都会在编译时失败:
add(A(1), A(2))
add(B(1), A(2))
add(B(1), B(2))
不幸的是,这不适用于弱一致性数值类型:
add(1, 1) // compiles
add(1.0, 1.0) // compiles
add(1, 1.0) // fails to compile
从 another post 来看,除了手动定义案例(当然还有一些辅助方法)之外,没有其他方法可以实现这一点。
如果我想创建一个 add 方法来添加两种不同类型的值,例如:
add[T,S](op1: T, op2: S): ? = ...
我能想到的最值得注意的例子是基本数字类型。如果我添加一个 Byte 和一个 Int,那么它将 return 一个 Int。如果添加两个字节,它可能 return 一个 Int 取决于字节的 -127 到 128 限制是否被打破。
此外,如果我想创建具有相同特征的 classes,我希望它也能这样做。
一个可能的解决方案是让 class 扩展相同的特征或 class。但是对于 Scala 原始类型的示例,这并不适用,因为 Int、Double、Float、Byte 除了 Any 之外没有共同的祖先。
我还查看了 Numeric[T] 特征,但在添加不同的基本类型时这似乎没有帮助。
谢谢 凯
这是某种联合类型类的主要示例。
首先定义一个类似 Numeric[T]
的东西,但为了可添加性:
trait Addable[T, S] {
type Result
def add(x: T, y: S): Result
}
现在,定义您的 add
函数:
def add[T,S](op1: T, op2: S)(implicit op: Addable[T, S]): op.Result =
op.add(op1, op2)
您剩下要做的就是为 Addable
:
// Put them in the companion object, so the implicits are available
// without explicit import
object Addable {
// Make any numeric addable
implicit def numericAddable[T : Numeric]: Addable[T, T] = {
new Addable[T, T] {
type Result = T
def add(x: T, y: T): T = {
val op = implicitly[Numeric[T]]
op.plus(x, y)
}
}
}
}
但您现在也可以定义自己的 类 并定义(非对称)加法能力:
case class A(x: Int)
case class B(x: Int)
case class C(x: Int)
implicit object AddABC extends Addable[A,B] {
type Result = C
def add(x: A, y: B): C = C(x.x + y.x)
}
这将允许您编写:
add(A(1), B(2))
但是,其中任何一个都会在编译时失败:
add(A(1), A(2))
add(B(1), A(2))
add(B(1), B(2))
不幸的是,这不适用于弱一致性数值类型:
add(1, 1) // compiles
add(1.0, 1.0) // compiles
add(1, 1.0) // fails to compile
从 another post 来看,除了手动定义案例(当然还有一些辅助方法)之外,没有其他方法可以实现这一点。