如何在Scala 2.13中对存在类型执行安全的模式匹配?

wvmv3b1j  于 2023-03-18  发布在  Scala
关注(0)|答案(2)|浏览(121)

**注:**这是一个人为的示例。

考虑下面的存在类型。

sealed trait Showable

final case class Show[A](show: A => String, value: A) extends Showable

我可以定义一个show方法如下:

def show(showable: Showable): String = showable match {
  case Show(show, value) => show(value)
}

但是模式匹配分别为showvalue推断Any => StringAny类型,因此,我也可以定义show方法如下:

def show(showable: Showable): String = showable match {
  case Show(show, value) => show(42)
}

这是不安全的。如何确保在case表达式中show只能应用于value

56lgkhnf

56lgkhnf1#

如果匹配键入的模式,则

def show(showable: Showable): String = showable match {
  case s: Show[a] => s.show(s.value)
}

def show(showable: Showable): String = showable match {
  case s: Show[_] => s.show(s.value)
}

编译但

def show(showable: Showable): String = showable match {
  case s: Show[a] => s.show(42)
}
//type mismatch;
// found   : Int(42)
// required: a

def show(showable: Showable): String = showable match {
  case s: Show[_] => s.show(42)
}
//type mismatch;
// found   : Int(42)
// required: _

不会。

ycl3bljg

ycl3bljg2#

您可以使用依赖类型使其类型安全

sealed trait Showable

sealed trait Show extends Showable {
  type Inner
  def value: Inner
  def show(a: Inner): String
}

object Show {
  type Aux[A] = Show {
    type Inner = A    
  }
  
  def apply[A](f: A => String, a: A): Aux[A] = new Show {
    type Inner = A
    def value: Inner = a
    def show(a: Inner) = f(a)
  }

  def unapply(show: Show): Option[(show.Inner => String, show.Inner)] = Option(a => show.show(a), show.value)
}


def show(showable: Showable): String = showable match {
  case Show(show, value) => show(value)
}

相关问题