我们假设以下内容:
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
方法是不可能的。出于多种设计原因,我试图保持这种方法的名称一致。有没有办法成功地做到这一点?
答案 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
。