当密封类型上的图案匹配时,Scala是否可以警告,但是,当返回类型密封时,我们可以检查功能是否返回所有情况?例如,考虑以下ADT
sealed trait Foo
case object Bar extends Foo
case object Qux extends Foo
然后在代数数据类型Foo
f: Foo => String
def f(x: Foo): String = x match {
case Bar => "bar"
}
提高警告
match may not be exhaustive.
It would fail on the following input: Qux
def f(x: Foo) = x match {
当返回类型是ADT时,例如在以下实现f: String => Foo
时,可以提出类似的非避免警告:
def f(x: String): Foo = x match {
case "bar" => Bar
// warn because we never return Qux
}
也许这不是一个真正的答案,但无论如何要发表评论。
模式匹配和函数返回值是两个不同的东西。前在 type 级别上运行,后者在 value 级别上进行操作。当您在Bar
上进行模式匹配时,您的模式匹配类型(例如Int
(。但是,当您返回Bar
时,您将返回案例对象值(例如42
(。
Suriftive函数定义为:
对于CODOMAN的每个成员 y ,至少存在一个成员 x 的域,因此 f(x(= y 。
现在很容易理解为什么此检查是不可行的/可能的。如果您的Bar
不是案例对象,而是一类怎么办?例如
final case class Bar(name: String, surname: String, age: Int)
您需要期望使用Bar
的所有可能值(例如名称=" John",姓氏=" Smith",年龄= 42(。
当然,这不是您的意图;您描述的是一个场景,每个子类型都有一个居民,因为Bar
和Qux
基本上是枚举,我可以理解为什么这样的检查对您有意义。但是,必须针对每(sub(类型的任意居民数量的一般情况实现,它需要验证CODOMAIN至少包含一个Bar
类型的值,至少一个值Qux
等值的值听起来很有用。
正如我所说,这并不是一个真正的答案,但是我想让您了解您要问的确切的内容。:)也许有人用反思和/或宏来写了一些可以提供这样的支票的东西,但据我所知。希望使用Scala 3枚举,无论如何您都不需要编写这样的功能。
这是 @luismiguelmejíasuárez和@slouc建议的枚举示例,确实提供了案例耗尽:
enumeratum
import enumeratum._
sealed trait Foo extends EnumEntry
object Foo extends Enum[Foo] {
val values = findValues
case object Bar extends Foo
case object Qux extends Foo
}
Foo.withName("Qux")
Scala 3枚举
enum Foo {
case Bar
case Qux
}
Foo.enumValueNamed("Qux"))
即使使用参数化密封类型也可以正常工作。