我拼命想要解决以下问题:
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"
。我该如何编译呢?
答案 0 :(得分:14)
您可能对lambda类型感兴趣。您在答案中使用的部分应用程序实际上是implemented in scalaz。 由于代码往往不太可读,因此他们开始使用lambda类型。有问题的类型可以写成
({type λ[α] = CList[α,A]})#λ
这可以通过在结构类型内的参数化类型λ
上创建类型投影来实现,从而捕获外部类型参数(在本例中为A
)。
您的答案中描述的与方差相关的其他问题可以通过在Res
协变中生成Access
参数来解决。
完成这些更改后,您的代码应如下所示:
trait Access[+Res[_]] { def access[C] : Res[C]}
trait CList[C, +A] extends Access[({type λ[α] = CList[α,A]})#λ]
答案 1 :(得分:2)
搜索“部分类型应用程序”我发现James Iry在scala辩论列表(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]
奶酪louise,这真的是2011年scala中唯一的方法吗?!!
修改强>
这在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"
答案 2 :(得分:2)
只是更新事物
将此编译器插件添加到您的 sbt 中进行实物投影,您将使用 ?
获得不错的语法。
这样就删除了看起来凌乱的类型投影样板!
因此,您可以编写 Either[String, ?]
addCompilerPlugin(“ org.spire-math” %%“实物投影仪”%“ 0.9.7”)
它在下面使用相同的旧式投影实现
您还可以在这里找到它:
https://underscore.io/blog/posts/2016/12/05/type-lambdas.html
答案 3 :(得分:0)
我知道这是一个非常古老的问题,但无论如何:
@GeneratedValue
答案 4 :(得分:0)
这是一种对我有用的“部分应用类型参数”的方法:
我有类似的功能
def foo[A, B, C, D, E](...)
这样,我只需要提示一个类型参数,编译器就可以推断出其余类型。这对我有用:
object InferType {
type InferType[A] = Option[A]
def apply[A]: Option[A] = None
}
更新foo以使用InferType类型的附加参数:
// t parameter is unused in implementation but
// is used by compiler to infer other type parameters
def foo[A, B, C, D, E](..., t: InferType[D])
用法:
foo(..., InferType[ConcreteD])