"inlining" 一个 val 后出现奇怪的类型错误
Strange type error after "inlining" a val
我发现 shapeless.everywhere
有一个非常奇怪的类型错误。考虑以下菊石脚本,它可以很好地加载 load.module
:
load.ivy("com.chuusai" %% "shapeless" % "2.3.0")
@
import shapeless._
import poly._
final case class Person(name: Person.Name, age: Person.Age)
object Person {
final case class Name(value: String) extends AnyVal
final case class Age(value: Int) extends AnyVal
}
def happyBirthday(person: Person, howManyYearsPast: Int): Person = {
object incAge extends ->((age: Int) => age + howManyYearsPast)
// THE MAGIC VAL
val oldPerson = everywhere(incAge)(person)
oldPerson
}
val john = Person(Person.Name("John Doe"), Person.Age(42))
val oldJohn = happyBirthday(john, 30)
现在,如果我尝试在此脚本中“内联”MAGIC VAL
,即将 val
替换为 everywhere(incAge)(person)
,我会莫名其妙地得到以下类型错误:
Main.scala:50: type mismatch;
found : person.type (with underlying type cachef6f1545a8d4dc31cb54d9957675f0559.Person)
required: shapeless.poly.Case[_1.type,shapeless.HNil]{type Result = ?} where val _1: shapeless.EverywhereAux[incAge.type]
everywhere(incAge)(person)
瓦特?
我想这应该归咎于 scalac 的黑魔法隐式解析,但我不知道这里发生了什么。如果有人能向我解开这个谜团,那就太好了(对我来说肯定有点启发)。
谢谢
我不知道这个问题的真正原因,但这是由影响隐式搜索和类型推断的预期类型引起的。您可以通过提供预期类型使非内联版本无法编译:
def happyBirthday(person: Person, howManyYearsPast: Int): Person = {
object incAge extends ->((age: Int) => age + howManyYearsPast)
val oldPerson: Person = everywhere(incAge)(person)
oldPerson
}
失败并出现完全相同的错误。
另一方面,您可以通过从函数中删除预期类型(又名 return 类型)来编译内联版本:
def happyBirthday(person: Person, howManyYearsPast: Int) = {
object incAge extends ->((age: Int) => age + howManyYearsPast)
everywhere(incAge)(person)
}
我很确定有人会认为这是一个 "bug",但是,类型推断是未指定的,所以需要一段时间才能弄清楚应该 发生了。
我发现 shapeless.everywhere
有一个非常奇怪的类型错误。考虑以下菊石脚本,它可以很好地加载 load.module
:
load.ivy("com.chuusai" %% "shapeless" % "2.3.0")
@
import shapeless._
import poly._
final case class Person(name: Person.Name, age: Person.Age)
object Person {
final case class Name(value: String) extends AnyVal
final case class Age(value: Int) extends AnyVal
}
def happyBirthday(person: Person, howManyYearsPast: Int): Person = {
object incAge extends ->((age: Int) => age + howManyYearsPast)
// THE MAGIC VAL
val oldPerson = everywhere(incAge)(person)
oldPerson
}
val john = Person(Person.Name("John Doe"), Person.Age(42))
val oldJohn = happyBirthday(john, 30)
现在,如果我尝试在此脚本中“内联”MAGIC VAL
,即将 val
替换为 everywhere(incAge)(person)
,我会莫名其妙地得到以下类型错误:
Main.scala:50: type mismatch;
found : person.type (with underlying type cachef6f1545a8d4dc31cb54d9957675f0559.Person)
required: shapeless.poly.Case[_1.type,shapeless.HNil]{type Result = ?} where val _1: shapeless.EverywhereAux[incAge.type]
everywhere(incAge)(person)
瓦特?
我想这应该归咎于 scalac 的黑魔法隐式解析,但我不知道这里发生了什么。如果有人能向我解开这个谜团,那就太好了(对我来说肯定有点启发)。
谢谢
我不知道这个问题的真正原因,但这是由影响隐式搜索和类型推断的预期类型引起的。您可以通过提供预期类型使非内联版本无法编译:
def happyBirthday(person: Person, howManyYearsPast: Int): Person = {
object incAge extends ->((age: Int) => age + howManyYearsPast)
val oldPerson: Person = everywhere(incAge)(person)
oldPerson
}
失败并出现完全相同的错误。
另一方面,您可以通过从函数中删除预期类型(又名 return 类型)来编译内联版本:
def happyBirthday(person: Person, howManyYearsPast: Int) = {
object incAge extends ->((age: Int) => age + howManyYearsPast)
everywhere(incAge)(person)
}
我很确定有人会认为这是一个 "bug",但是,类型推断是未指定的,所以需要一段时间才能弄清楚应该 发生了。