【问题标题】:Define a type constructor to build a type lambda (partially applied type)定义类型构造函数来构建类型 lambda(部分应用类型)
【发布时间】:2014-04-24 12:46:36
【问题描述】:

我在定义类型构造函数以消除 Scala 中用于部分类型应用程序的可怕的 type-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
                                                           ^

【问题讨论】:

    标签: scala higher-kinded-types


    【解决方案1】:

    除了使用类型投影,我似乎找不到解决方案,只是更短:

    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)
    

    【讨论】:

      猜你喜欢
      • 2019-09-06
      • 1970-01-01
      • 1970-01-01
      • 2019-05-22
      • 2019-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多