scala - 泛型列表上的模式匹配
问题描述
我有一个类,其中包含一个泛型类型的序列,例如:
sealed trait Interface {}
case class Imp1() extends Interface {}
case class Imp2() extends Interface {}
case class Wrapper[+I <: Interface](interface: I) {}
case class WrapperList(list: Seq[Wrapper[Interface]]) {
...
}
在WrapperList
我希望能够遍历每个类型的包装序列和模式匹配,例如。
def getImp1s(remaining: Seq[Wrapper[Interface]] = list): Seq[Wrapper[Imp1]] = {
if (remaining.length == 0) Seq()
else remaining.head match {
case wrapper: Wrapper[Imp1] => get(remaining.tail) :+ wrapper
case _ => get(remaining.tail)
}
}
你可能会猜到我遇到了
non-variable type argument Playground.Imp1 in type pattern Playground.Wrapper[Playground.Imp1] is unchecked since it is eliminated by erasure
为了克服这个问题,我认为我可以使用TypeTags
或ClassTags
保留类型,例如:
case class Wrapper[+I <: Interface](interface: I)(implicit tag: TypeTag[I]) {}
但是,这似乎不起作用,我仍然收到相同的警告。有人可以解释我如何使用 TypeTag 进行匹配吗?我宁愿避免创建扩展通用抽象类的通用类的具体版本,但请理解这可能是最简单的解决方案。
谢谢你的帮助 :)
解决方案
尝试
import shapeless.TypeCase
val `Wrapper[Imp1]` = TypeCase[Wrapper[Imp1]]
def getImp1s(remaining: Seq[Wrapper[Interface]]): Seq[Wrapper[Imp1]] = {
if (remaining.isEmpty) Seq()
else remaining.head match {
case `Wrapper[Imp1]`(wrapper) => getImp1s(remaining.tail) :+ wrapper
case _ => getImp1s(remaining.tail)
}
}
getImp1s(Seq(Wrapper(Imp1()), Wrapper(Imp2()), Wrapper(new Interface {})))
// List(Wrapper(Imp1()))
getImp1s(Seq(Wrapper(Imp2()), Wrapper(Imp1()), Wrapper(new Interface {})))
// List(Wrapper(Imp1()))
无需使用自定义提取器的 Shapeless 也可以实现相同的效果
object `Wrapper[Imp1]` {
def unapply(arg: Any): Option[Wrapper[Imp1]] = arg match {
case Wrapper(Imp1()) => Some(Wrapper(Imp1()))
case _ => None
}
}
或直接
def getImp1s(remaining: Seq[Wrapper[Interface]]): Seq[Wrapper[Imp1]] = {
if (remaining.isEmpty) Seq()
else remaining.head match {
case Wrapper(Imp1()) => getImp1s(remaining.tail) :+ Wrapper(Imp1())
case _ => getImp1s(remaining.tail)
}
}
或者
def getImp1s(remaining: Seq[Wrapper[Interface]]): Seq[Wrapper[Imp1]] = {
if (remaining.isEmpty) Seq()
else remaining.head match {
case Wrapper(_: Imp1) => getImp1s(remaining.tail) :+ Wrapper(Imp1())
case _ => getImp1s(remaining.tail)
}
}
推荐阅读
- discord - Discord Python - 多个前缀
- flutter - OverlayEntry 捕获 PointerEvents,但也将它们转发到主应用程序
- reactjs - 为什么上传文件时react.js会返回cors
- reactjs - NextJS 快速刷新是否适用于非组件文件?
- c# - 如何检查文件列表的文件内容是否相同?
- flutter - 如何重新计算图像大小的值
- excel - 使用 index + Match 在给定条件下获取值
- windows - 无法在 Windows 上为 CURA 运行 nmake,正文中给出了链接
- arrays - 不同的密码如何重定向到 php 和 html 中的不同页面
- azure - ARM 部署错误 - 请求内容无效,无法反序列化:'无法反序列化当前 JSON 数组