带有 ADT 和 Aux 模式的类型安全 [英] Type-safety with ADT and Aux pattern

查看:59
本文介绍了带有 ADT 和 Aux 模式的类型安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计带有 ADT 和 Aux-pattern 的类型安全代码并且无法摆脱一些 asInstanceOf.例子如下:

I'm designing type-safe code with ADT and Aux-pattern and cannot get rid of some asInstanceOf. Here is the example:

  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 是正确的,但有没有办法得到它?

In this case it is pretty obvious that asInstanceOf is correct, but is there a way to get rig of it?

我正在考虑 S <: Source: ClassTag,但它在这里似乎没有用.也许其他反射技巧?

I was considering S <: Source: ClassTag, but it doesn't seem to be useful here. Maybe other reflection trick?

推荐答案

请看说明为什么签名

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")
    )
  }
}

不起作用,有几种方法可以解决它:

doesn't work and several approachs how to fix it:

泛型函数,其中返回类型取决于 Scala 中的输入类型?

如果将 A 的泛型子类型声明为返回参数,为什么我不能返回 A 的具体子类型?

模式匹配中使用的抽象类型的类型不匹配

例如尝试一个类型类

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)

这篇关于带有 ADT 和 Aux 模式的类型安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆