"内联"之后的奇怪类型错误一个val

时间:2016-04-19 17:11:38

标签: scala shapeless

我用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)

WAT?

我想scalac的黑魔法隐含的解决方案应该受到指责,但我不知道这里发生了什么。如果有人可以向我解开这个谜团,那就太棒了(对我来说肯定有些启发)。

由于

1 个答案:

答案 0 :(得分:4)

我不知道此问题的真正原因,但它是由影响隐式搜索和类型推断的预期类型引起的。您可以通过提供预期类型来使非内联版本无法编译:

def happyBirthday(person: Person, howManyYearsPast: Int): Person = {
  object incAge extends ->((age: Int) => age + howManyYearsPast)
  val oldPerson: Person = everywhere(incAge)(person)
  oldPerson
}

失败并出现完全相同的错误。

另一方面,您可以通过从函数中删除预期类型(又名返回类型)来编译内联版本:

def happyBirthday(person: Person, howManyYearsPast: Int) = {
  object incAge extends ->((age: Int) => age + howManyYearsPast)
  everywhere(incAge)(person)
}

我很确定可以认为这是一个"错误"但是,类型推断是未指定的,所以它需要花一些时间来弄清楚究竟是什么应该发生。