scala - Scalafiddle中的Simulacrum:宏扩展期间的异常
问题描述
我想在 Scalafiddle 中使用Simulacrum,例如:
import simulacrum._
@typeclass trait Ordering[T] {
def compare(x: T, y: T): Int
@op("<") def lt(x: T, y: T): Boolean = compare(x, y) < 0
@op(">") def gt(x: T, y: T): Boolean = compare(x, y) > 0
}
这给了我以下错误:
ScalaFiddle.scala:3: error: exception during macro expansion:
scala.reflect.macros.TypecheckException: not found: type op
at scala.reflect.macros.contexts.Typers.$anonfun$typecheck$3(Typers.scala:32)
...
这是小提琴:https ://scalafiddle.io/sf/vT0X9FR/4
我错过了什么吗?
解决方案
您的代码没有问题,问题出在 ScalaFiddle 上。
如果我尝试在scastie(Scala 的类似 Web IDE)中运行您的代码,并打印出它生成的类型树,您可以看到以下内容:
|-- class Playground BYVALmode-EXPRmode (site: package <empty>)
| |-- new op("<") EXPRmode (silent: class Playground)
您可以看到 scastie 导致生成的代码被包装在一个Playground
类中,该类未在您的代码中定义,而是由 Web IDE 为您提供的。
如果我在 IDEA 中编译相同的示例,我会看到以下内容:
|-- new op("<") EXPRmode (silent: package github)
| |-- new op BYVALmode-EXPRmode-FUNmode-POLYmode (silent: package github)
op
如您所见, simulacrum 创建的类型没有包装。由于这种包装,simulacrum 无法找到op
它生成的类型,因为它在编译时的完整命名空间是Playground.op
.
为了避免这种情况并作为一种解决方法,请将您的特征包装在一个对象中:
import simulacrum._
object Foo {
@typeclass trait Ordering[T] {
def compare(x: T, y: T): Int
@op("<") def lt(x: T, y: T): Boolean = compare(x, y) < 0
@op(">") def gt(x: T, y: T): Boolean = compare(x, y) > 0
}
@typeclass trait Numeric[T] extends Ordering[T] {
@op("+") def plus(x: T, y: T): T
@op("*") def times(x: T, y: T): T
@op("unary_-") def negate(x: T): T
def zero: T
def abs(x: T): T = if (lt(x, zero)) negate(x) else x
}
import Foo.Numeric.ops._
def signOfTheTimes[T: Numeric](t: T): T = -(t.abs) * t
}
推荐阅读
- python - 使用未正确执行的自动化代码
- html - 避免在 h2 元素后分页 200px
- r - 如何用公式格式化ggplot`geom_text`,得到不需要的“c(...)”
- mysql - MySQL从同一行不同列中选择最后输入日期和值
- reactjs - redux-form 验证:最小长度和匹配密码
- python - 两组生成html标签
- javascript - 我如何构建我的代码以使对象位于它们自己的文件中?
- sql - Oracle SQL 面试关于物化视图的问题?
- mysql - 显示从 mysql 数据库到 laravel 刀片视图的 json 数组数据
- amazon-web-services - 错误:找不到 JobId 服务:AmazonRekognition;状态码:400;