2011-04-03 66 views
12

我拼命地解决以下几个:部分应用型参数

trait Access[Res[_]] { def access[C]: Res[C] } 

trait CList[C1, A] extends Access[CList[_, A]] // ?! 

def test[C1, C2, A](c: CList[C1, A]): CList[C2, A] = c.access[C2] 

scalac只是说:"error: illegal cyclic reference involving trait CList"。我怎样才能编译?

回答

13

您可能会感兴趣的类型lambda表达式,你在你的答案中所使用的部分应用程序实际上是implemented in scalaz 由于代码的可读性往往会降低,但他们开始使用类型lambdas代替。所讨论的类型可以写为

({type λ[α] = CList[α,A]})#λ 

这可以通过在结构类型内的参数化类型λ上创建类型投影来捕获外部类型参数(在本例中为A)。

在答案中描述的有关方差的其他问题可以通过使参数Access中的Res协变来解决。

这些改变你的代码应该是这样的后:

trait Access[+Res[_]] { def access[C] : Res[C]} 

trait CList[C, +A] extends Access[({type λ[α] = CList[α,A]})#λ] 
+0

谢谢,这看起来好一点。此外,因为在我的真实情况下CList的类型参数有上限,有一个专用的特质Partial2并不真正有用(我需要为边界等添加类型参数) – 2011-04-03 15:25:18

+0

此外,如果您的代码中经常使用类型lambdas,考虑下面的编译器插件: https://github.com/non/kind-projector – 2017-11-12 10:49:23

2

google搜索“部分类型的应用程序”,我发现这个解决方案张贴詹姆斯IRY阶辩论名单(http://scala-programming-language.1934581.n4.nabble.com/Partial-type-inference-td2007311.html;适合于使该ARG顺序被改变):

type Partial2[T[_,_], B] = { 
    type Apply[A] = T[A,B] 
} 
trait CList[C1, A] extends Access[Partial2[CList, A]#Apply] 

奶酪路易丝,这是真的只有在2011年斯卡拉这样做的方法?!

编辑:

这种失败,协方差A:。, - (

trait Access[Res[_]] { def access[C]: Res[C] } 

type Partial2[T[_,_], B] = { 
    type Apply[A] = T[A,B] 
} 
trait CList[C1, +A] extends Access[Partial2[CList, A]#Apply] 

"covariant type A occurs in invariant position" 
0

我知道这是一个非常古老的问题,但无论如何:

trait AnyAccess { 
    type Res[X] 
    def access[Z]: Res[Z] 
} 

trait AnyCList extends AnyAccess { me => 
    type C 
    type A 
    // this could be a subtype bound instead, if needed 
    type Res[X] = AnyCList { type C = X; type A = me.A } 
} 
case object AnyCList { 
    type of[C0, +A0] = AnyCList { type C = C0; type A <: A0 } 
} 

case object buh { 

    def test[C1, C2, A](c: AnyCList.of[C1, A]): AnyCList.of[C2, A] = c.access[C2] 
}