定义一个类型构造函数来构建一个类型lambda(部分应用的类型)

时间:2014-04-24 12:46:36

标签: scala higher-kinded-types

我在定义类型构造函数时遇到问题,以废除Scala中部分类型应用程序的可怕类型lambda方法。给出:

trait Sys[S <: Sys[S]]

trait Expr[S <: Sys[S], +A] {
  def value: A
}

import reflect.ClassTag

trait Proc[S <: Sys[S]] {
  def attribute[A[~ <: Sys[~]]](key: String)
                               (implicit tag: ClassTag[A[S]]): Option[A[S]]
}

我们说我有这种方法:

def name[S <: Sys[S]](p: Proc[S]): String = 
  p.attribute[({type A[~ <: Sys[~]] = Expr[~, String]})#A]("name")
    .fold("<unnamed>")(_.value)

我想把它定义为:

def name[S <: Sys[S]](p: Proc[S]): String = 
  p.attribute[XXX[String]]("name").fold("<unnamed>")(_.value)

问题是:如何定义类型构造函数XXX[A]

我的想法是:

type XXX[A] = ({type Ex[S <: Sys[S]] = Expr[S, A]})#Ex

但它只产生

<console>:52: error: type Ex takes type parameters
       type XXX[A] = ({type Ex[S <: Sys[S]] = Expr[S, A]})#Ex
                                                           ^

1 个答案:

答案 0 :(得分:0)

我似乎找不到除了保持类型投影之外的解决方案,只是缩短了:

trait Ex[A] { type L[S <: Sys[S]] = Expr[S, A] }

def name[S <: Sys[S]](p: Proc[S]): String = 
  p.attribute[Ex[String]#L]("name").fold("<unnamed>")(_.value)

这仍然不是我想要的。我可以完全摆脱类型投射吗?


第二个想法是提供一种扩展方法:

implicit class RichProc[S <: Sys[S]](val `this`: Proc[S]) extends AnyVal {
  def attrExpr[A](key: String)
                 (implicit tag: ClassTag[Expr[S, A]]): Option[Expr[S, A]] =
    `this`.attribute[({type Ex[~ <: Sys[~]] = Expr[~, A]})#Ex](key)
}

def name[S <: Sys[S]](p: Proc[S]): String = 
  p.attrExpr[String]("name").fold("<unnamed>")(_.value)