我正在使用 ADT 和 Aux 模式设计类型安全代码,并且无法摆脱一些asInstanceOf
。这是示例:
sealed trait Source
case object FileSystem extends Source
case object Network extends Source
sealed trait Data {
type S <: Source
}
object Data {
type Aux[T <: Source] = Data { type S = T }
}
case class RegularFile(path: String) extends Data { type S = FileSystem.type }
case class Directory(path: String) extends Data { type S = FileSystem.type }
case class UnixDevice(path: String) extends Data { type S = FileSystem.type }
case class Remote(ip: String) extends Data { type S = Network.type }
//Lots of asInstanceOf
def availableData[S <: Source](src: Source): List[Data.Aux[S]] = {
src match {
case FileSystem => List(
RegularFile("/tmp/test").asInstanceOf[Data.Aux[S]],
Directory("/home/somename").asInstanceOf[Data.Aux[S]],
UnixDevice("/dev/null").asInstanceOf[Data.Aux[S]],
)
case Network => List(
Remote("192.168.0.1").asInstanceOf[Data.Aux[S]]
)
}
}
在这种情况下,很明显asInstanceOf
是正确的,但是有没有办法摆脱它呢?
我正在考虑S <: Source: ClassTag
,不过这里好像没什么用。也许还有其他反射技巧?
请参阅解释为什么签名
def availableData[S <: Source](src: S): List[Data.Aux[S]] = {
src match {
case FileSystem => List(
RegularFile("/tmp/test"),
Directory("/home/somename"),
UnixDevice("/dev/null"),
)
case Network => List(
Remote("192.168.0.1")
)
}
}
不起作用,有几种修复方法:
Scala 中返回类型取决于输入类型的通用函数? https://stackoverflow.com/questions/64318180/generic-function-where-the-return-type-depends-on-the-input-type-in-scala
如果将 A 的泛型子类型声明为返回参数,为什么我不能返回 A 的具体子类型? https://stackoverflow.com/questions/61668592/why-cant-i-return-a-concrete-subtype-of-a-if-a-generic-subtype-of-a-is-declared/
模式匹配中使用的抽象类型的类型不匹配 https://stackoverflow.com/questions/52479695/type-mismatch-on-abstract-type-used-in-pattern-matching
例如尝试一个类型类
trait AvailableData[S <: Source] {
def availableData(src: S): List[Data.Aux[S]]
}
object AvailableData {
implicit val fileSystem: AvailableData[FileSystem.type] = _ =>
List[Data.Aux[FileSystem.type]](
RegularFile("/tmp/test"),
Directory("/home/somename"),
UnixDevice("/dev/null"),
)
implicit val network: AvailableData[Network.type] = _ =>
List[Data.Aux[Network.type]](
Remote("192.168.0.1")
)
}
def availableData[S <: Source](src: S)(implicit
ad: AvailableData[S]
): List[Data.Aux[S]] = ad.availableData(src)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)