添加依赖于类型类的有效性检查(可选隐式)
在 scala 中,我们可以使用隐式类型类根据参数化类型的参数有条件地将方法添加到该类型上。例如,Iterator.sum:
def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)
必须有 Numeric 类型类的实例才能调用此方法:到目前为止
scala> List(1, 2, 3).sum
res0: Int = 6
scala> List("a", "b").sum
<console>:6: error: could not find implicit value for parameter num: Numeric[java.lang.String]
List("a", "b").sum
^
,一切顺利。假设我想要某种集合类型,My2Col
:
class My2Col[A](a1 : A, a2 : A)
但我想强制执行,如果这是用 A : Numeric
制作的, 然后 a2 > a1 。但是,使用非数字的
A
来创建它完全有效。
My2Col("a", "b") //OK
My2Col("b", "a") //OK
My2Col(1, 2) //OK
My2Col(2, 1) //THROW IllegalArgumentException
有人对我如何做到这一点有任何想法吗?
PS。如果有人对更好的问题标题有任何建议,我会洗耳恭听
In scala, we can use implicit typeclasses to conditionally add methods onto a parameterized type dependent on that type's parameters. For example, Iterator.sum
:
def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)
There must be an instance of the Numeric
typeclass for this method to even be called:
scala> List(1, 2, 3).sum
res0: Int = 6
scala> List("a", "b").sum
<console>:6: error: could not find implicit value for parameter num: Numeric[java.lang.String]
List("a", "b").sum
^
So far, so good. Let's say I want to have some collection type, My2Col
:
class My2Col[A](a1 : A, a2 : A)
But I want to mandate that, if this is made with a A : Numeric
, then a2 > a1
. However, it is entirely valid for it to be made with an A
which is not numeric.
My2Col("a", "b") //OK
My2Col("b", "a") //OK
My2Col(1, 2) //OK
My2Col(2, 1) //THROW IllegalArgumentException
Has anyone any ideas as to how I might do this?
PS. If anyone has any suggestions for a better question title, I'm all ears
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我将通过创建 2 个表示需求的隐式来实现这一点,一个更通用(对于除
Int
或Numeric[T]
之外的所有类型),另一个更通用更具体(对于Int
或Numeric[T]
)。然后,按照隐式解析的规则,我会将更具体的一个放在
Requirement
类型的伴生对象中,将更通用的一个放在伴生对象的基类中。这样我可以确保编译器首先尝试应用更具体的。当然,缺点是如果用户显式提供隐式参数,则可以绕过此机制而不进行检查。
像这样的东西(其中
Int
是具有特定规则的类型,Foo
是集合类):I would implement this by creating 2 implicits that represent requirements, one being more general (for all types other than, say,
Int
orNumeric[T]
), and the other being more specific (forInt
orNumeric[T]
).Then, following the rules of implicit resolution, I would put the more specific one in the companion object of the
Requirement
type, and the more general one in the base class of the companion object. This way I would ensure that the compiler tries to apply the more specific one first.Of course, the downside is that if the user were to explicitly provide the implicit parameter, this mechanism could be circumvented not to do the check.
Something like this (where
Int
is the type with specific rules, andFoo
is the collection class):