【发布时间】:2020-07-11 11:31:33
【问题描述】:
我一直在尝试确定如何编写一个类型参数,将函数限制为支持关系运算符的类型?
例如:
def biggerOf[A <: ???](a: A, b: A): A = { if (a > b) a else b }
??? 是我的难题。高级类型参数位对我来说是新的,所以寻求一点帮助。认为 AnyVal 可能是赢家,但对于 Unit 类型(和 Boolean 不会破坏,但也不会工作)。感谢您的任何想法。
【问题讨论】:
我一直在尝试确定如何编写一个类型参数,将函数限制为支持关系运算符的类型?
例如:
def biggerOf[A <: ???](a: A, b: A): A = { if (a > b) a else b }
??? 是我的难题。高级类型参数位对我来说是新的,所以寻求一点帮助。认为 AnyVal 可能是赢家,但对于 Unit 类型(和 Boolean 不会破坏,但也不会工作)。感谢您的任何想法。
【问题讨论】:
您想要使用 Ordering 类型类。
import scala.math.Ordering.Implicits.infixOrderingOps
def biggerOf[A:Ordering](a: A, b: A): A = { if (a > b) a else b }
A:Ordering 将A 限制为Ordering 类型类中的类型,infixOrderingOps 启用便利运算符(方法),例如<、>= 等。
【讨论】:
【讨论】:
scala.math.Ordering.Implicits.infixOrderingOps 让我非常清楚使这些解决方案起作用的基本“什么”就是全部。
正如 Luis 和 jwvh 所建议的,您可以使用 Ordering 类型类,但我想向您介绍类型类模式并使用类型类来更深入地限制函数的使用。
类型类允许一个人在其泛型类型中具有灵活性,同时对其进行足够的限制,以至于那些没有该类型类实例的人可能无法使用您的函数。
以这个为例,假设 Scala 中的 Numerical 数据类型上没有操作符,我们可以通过引入 Num 类型类,然后通过指定它们在操作上的行为来概括对它们进行操作的想法,因为这些 Numerical数据类型有不同的处理代数运算的方法。 (例如整数与实数)
trait Num[A] {
def add(l: A, r: A): A
def sub(l: A, r: A): A
def mul(l: A, r: A): A
def div(l: A, r: A): A
}
object NumTest {
def addThenMultiply[A](l: A, r: A)(implicit ev: Num[A]): A =
ev.mul(ev.add(l, r), r)
//then we create Num instances for numerical types
implicit val intNum = new Num[Int] { /* implementation*/ }
implicit val floatNum = new Num[Float] { /* implementation */ }
}
现在在这种情况下,函数 addThenMultiply 仅适用于 Int 和 Float 数据类型,因为它们是唯一具有 Num 实例的函数,但您也可以为其他自定义数据类型添加实例,具体取决于根据您的需要。
【讨论】: