2012-12-06 81 views
2
界定

是否有可能進入更高kinded類型的類型構造函數的參數在上下文的約束?我正在尋找定義一個採用更高親和類型的特徵,並且有一個返回構造函數參數實例的方法。類型構造參數具有較高的kinded類型

case class A[TContents](c: TContents) { 
    def foo = c 
} 

case class B[TContents](c: TContents) { 
    def foo = c 
} 

trait Fooable[TClass[_ <: TContents], TContents] { 
    def foo(obj: TClass[TContents]): TContents 
} 

case class AFooable[TContents] extends Fooable[A, TContents] { 
    def foo(obj: A[TContents]) = obj.foo 
} 

case class BFooable[TContents] extends Fooable[B, TContents] { 
    def foo(obj: B[TContents]) = obj.foo 
} 

class test { 
    def getFoo[TType[_] : Fooable, TContents](obj: TType[TContents]): TContents = 
    implicitly[Fooable[TType, TContents]].foo(obj) 

    implicit def aFooable = AFooable 

    val a = A(1) 
    val foo = getFoo(a) 
} 

這種失敗,編譯器錯誤抱怨這種情況下邊界不能有兩個類型參數,但我不能找到另一種方式來訪問類構造函數的參數?

回答

3

你有兩個選擇,要麼使用type lambda trick部分地適用Fooable(啊):

def getFoo[TType[_]: ({type L[A[_]] = Fooable[A, TContents]})#L, TContents](
    obj: TType[TContents] 
): TContents = implicitly[Fooable[TType, TContents]].foo(obj) 

或者desugar約束(好多了,在我看來)上下文:

def getFoo[TType[_], TContents](obj: TType[TContents])(
    implicit ev: Fooable[TType, TContents] 
): TContents = ev.foo(obj) 

注無論哪種情況,您都需要爲您的aFooable輸入一個類型參數:

implicit def aFooable[A] = AFooable[A] 

而且我強烈建議遵守有關參數列表少case類的警告。

+0

感謝您的建議。正如我所懷疑的,上下文邊界的語法糖不能處理多個類型參數。我不知道這是否是監督或語言的限制? – Woodz

+0

許多人想要部分應用類型出於不同的原因(你的情況是其中之一);請參閱例如[this compiler plugin](https://github.com/non/kind-projector)。但是,爲了回答你的問題,我猜想這是一個有意識的決定,以避免更多的Scala語法。 –

相關問題