Scala 部分应用类型参数
我拼命地想解决以下问题:Scala 部分应用类型参数,scala,higher-kinded-types,Scala,Higher Kinded Types,我拼命地想解决以下问题: 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只是说:“错误:涉及trait CList的非法循环引用”。如何进行编译?通过谷歌搜索“部分类型应用程序”,我在scala辩
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只是说:“错误:涉及trait CList的非法循环引用”
。如何进行编译?通过谷歌搜索“部分类型应用程序”,我在scala辩论列表上找到了James Iry发布的解决方案(;经过调整,因此参数顺序发生了变化):
cheese louise,这真的是2011年在scala做到这一点的唯一方法吗
编辑:
此操作失败,协方差在A
:-(
您可能对lambdas类型感兴趣。您在回答中使用的部分应用程序实际上是。 但是,由于代码的可读性越来越差,他们开始使用lambdas类型
({type λ[α] = CList[α,A]})#λ
其工作原理是在结构类型内部的参数化类型λ
上创建类型投影,从而捕获外部类型参数(在本例中为a
)
答案中描述的关于方差的另一个问题可以通过使Access
中的Res
参数协变来解决
在这些更改之后,您的代码应该如下所示:
trait Access[+Res[_]] { def access[C] : Res[C]}
trait CList[C, +A] extends Access[({type λ[α] = CList[α,A]})#λ]
我知道这是一个很老的问题,但无论如何:
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]
}
trait-AnyAccess{
类型Res[X]
def访问[Z]:分辨率[Z]
}
trait AnyCList扩展AnyAccess{me=>
C型
A型
//如果需要,这可以是子类型绑定
类型Res[X]=AnyCList{type C=X;type A=me.A}
}
case对象AnyCList{
类型[C0,+A0]=AnyCList{type C=C0;类型A只是为了更新东西
将此编译器插件添加到您的sbt中,以进行种类投影,您将使用?
获得一个很好的语法
这将删除看起来凌乱的类型投影样板文件!
因此,您可以编写类似于的内容,如[String,?]
addCompilerPlugin(“org.spire math”%%“kind projector”%%“0.9.7”)
它是用下面相同的旧类型投影实现的
您也可以在这里找到它:
这里有一个方法对我来说“部分应用类型参数”:
我有一个函数,比如
def foo[A, B, C, D, E](...)
因此,我只需要提示一个类型参数,编译器就可以推断出其余的类型参数。这对我来说很有效:
object InferType {
type InferType[A] = Option[A]
def apply[A]: Option[A] = None
}
更新foo以获取推断类型的附加参数:
// 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])
谢谢,这看起来好一点。另外,因为在我的真实情况下,CLIST的类型参数有上界,有一个专用的特性PARTAL2不是很有帮助(我需要为边界添加类型参数)。如果在代码中经常使用类型LAMBDAS,请考虑下面的编译器插件:
// 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])