2012-04-03 60 views
2

我想创建一个Scala Id类型类型,例如,我可以声明类型为Foo的Id需要Long值,例如,我如何让scala编译器从另一个类推断一种类型?

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]需要一个长?

回答

3

你有权摆脱WithId上的那个类型参数。但是,出现的第二个问题是由于您如何实例化Id而导致的。当你说val x: Foo[T]时,你指定了你想要的类型x,但是你并没有真正帮助编译器解决什么类型的Foo应该在构建时使用。所以...编译器错误,你得到的结果是说Foo你想IdA,但你还没有告诉Foo什么A甚至是!要修复它,只需将您的用法更改为

val fooId = Id[Foo](12L) 
+0

有趣。我没有想到这种类型的“切换边”会很重要,因此可以这么说,如果它在左边,它会被插入到右边。谢谢! – 2012-04-03 20:53:13

相关问题