部分应用类型参数

时间:2011-04-03 04:59:43

标签: 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只是说:"error: illegal cyclic reference involving trait CList"。我该如何编译呢?

5 个答案:

答案 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])