如何让scala编译器推断另一种类型?

时间:2012-04-03 18:54:49

标签: scala compiler-construction types typeclass parameterized

我想创建一个Scala Id类型类,例如,我可以声明类型Foo的Id采用Long值,例如

val fooId: Id[Foo] = Id(12L) // type-safe at compile time
val fooIdValue: Long = fooId.value // able to get the value back out

我尝试了各种各样的方法,但我似乎无法强制执行约束。如果我宣布

trait WithId[I] {
  type Id = I
}

case class Id[A <: WithId[_]](value: A#Id) // A#Id => Any, not what I want!

class Foo extends WithId[Long] {
  type Id = Long
}

这允许

val fooId: Id[Foo] = Id("foo") // should be illegal unless a Long

如果我改变WithId以使用抽象类型

trait WithId {
  type Id
}

case class Id[A <: WithId](value: A#Id)

class Foo extends WithId {
  type Id = Long
}

然后

val fooId: Id[Foo] = Id(12L)

没有编译,说

no type parameters for method apply: (value: A#Id)net.box.Id[A] in object Id exist so that it can be applied to arguments (Long)  --- because --- argument expression's type is not compatible with formal parameter type;  found   : Long  required: ?0A#Id

我怎么能说并强制执行Id [Foo]需要很长时间?

1 个答案:

答案 0 :(得分:3)

你在WithId上摆脱那个类型参数是对的。但是,出现的第二个问题是由于您如何实例化Id。当你说val x: Foo[T]时,你指的是你希望x拥有什么类型,但是你并没有真正帮助编译器找出Foo应该使用的类型建造。所以...你得到Foo Id A Foo的结果导致编译错误,但你没有告诉A什么val fooId = Id[Foo](12L) 甚至是!要解决此问题,只需将您的使用情况更改为

即可
{{1}}