【问题标题】:How to redefine operations for Scala type tags如何重新定义 Scala 类型标签的操作
【发布时间】:2020-08-03 00:17:40
【问题描述】:

假设我有一个标记类型,例如:

import shapeless.tag.@@
import shapeless.tag

trait VolumeTag
type Volume = Double @@ VolumeTag

def Volume(value: Double): Volume = tag[Volume][Double](value)

现在,我遇到的问题是,例如,当我添加两个 Volume 类型的对象时,我得到一个双精度数。如何重新定义+ 运算符,使两个卷的返回值为一个卷?

我尝试添加一个新特征,例如。 VolumeOperationsVolume 类型的对象重新定义 +。但是我无法在不使用.isInstanceOf[Volume] 的情况下实现+

是否可以在不强制转换的情况下实现这一目标?

【问题讨论】:

    标签: scala types operator-overloading shapeless


    【解决方案1】:

    你可以定义扩展方法

    def Volume(value: Double): Volume = tag[VolumeTag][Double](value)
    
    implicit class VolumeOp(v: Volume) {
      //def +(v1: Volume): Volume = Volume(v + v1)
      def plus(v1: Volume): Volume = Volume(v + v1)
    }
    

    tag 实际上是在投射。

    【讨论】:

    • 似乎对我不起作用。我可以在VolumeOp 中定义一个额外的plus(v1: Volume) 函数,它会起作用。但是,重新定义+ 不会(即,添加两个卷仍将返回一个双倍,不知何故找不到新的+,而是双倍的那个)。我正在使用 Scala 2.13.1
    • @BKE 是的,你是对的。扩展将适用于plus,而不适用于+。您可以将def Volume 设为隐式,然后写入Volume(1.0) + Volume(2.0) : Volume
    • 我不知道为什么它不起作用,而且它有点违背了目的。这几乎比写 Volume(Volume(1.0) + Volume(2.0) 更好。但如果你能解释为什么它不能按我想要的方式工作,我会接受你的回答。
    • @BKE 编译器不会选择使用隐式定义的方法,如果已经存在同名的显式方法。 scala-lang.org/files/archive/spec/2.13/07-implicits.html#views
    • 好的,有没有隐含的解决方案?
    猜你喜欢
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多