2012-04-03 62 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

相關問題