路径依赖/嵌套类型

时间:2015-10-01 10:41:04

标签: scala

我们假设以下内容:

class Wrapper1 {
  case class Condition(test: String)
}
object Wrapper1 extends Wrapper1

class Wrapper2 {
  case class Condition[A](test: String)
}
object Wrapper2 extends Wrapper2


class Test 
  type T = // whatever

  def test(fn: T => Wrapper1.Condition): X
  def test[R](fn: T => Wrapper2.Condition[R]): X
}

问题在于,由于类型擦除,这些方法在擦除后具有完全相同的类型。可以很容易地改变第二个的签名:

def test[R](fn: T => Wrapper2.Condition[R])(implicit ev: R =:= R): X

但这会混淆编译器并在其他地方使用test方法是不可能的。出于多种设计原因,我试图保持这种方法的名称一致。有没有办法成功地做到这一点?

2 个答案:

答案 0 :(得分:0)

似乎这不是Scala double definition (2 methods have the same type erasure)

的副本

我的建议......只需一个方法

def test[Cond: TypeTag](fn: T => Cond): X = {
  if(typeOf[T] <:< typeOf[Wrapper1.Condition]) ...
  else if(typeOf[T] <:< typeOf[Wrapper2.Condition[_]) ...
  else ...
}

答案 1 :(得分:0)

终于能够解决了。我所追求的是一种有条件地附加到HList的方法。基本上,同一方法的多次重载必须共存,因为它们会返回不同类型的HList

要只有一个方法,需要参数来指示方法的最终签名是什么样的。

因此,让我们假设以下内容,test方法必须返回

def test[RR](arg: Type1[RR]): Wrapper[RR :: ExistingHList]

或分别:

def test(arg: Type2): Wrapper[ExistingList]

根据参数是否满足某些条件,相同的方法必须附加到Hlist。此修复程序与使用shapeless.ops.hlist.Prepend一样简单,默认情况下会在我们尝试将HList附加到hlist时返回现有HNil

使Type2的参数返回HNil或隐式转换为最终为HNil的内容是有效的方法。

具体做法是:

  class Wrapper[PS <: HList] {
    def test[
      RR,
      HL <: HList,
      Out <: HList
    ](
      condition: T => Wrapper[HL]
    )(implicit prepend: Prepend.Aux[HL, PS, Out]): Wrapper[Out[
  }

如果条件函数在函数不需要修改结束返回类型的情况下返回Wrapper[HNil],则此方法有效。修改过的函数可以自由地独立构建自己的HList