考虑我两次尝试编写相同的函数:
data Foo = Bar Int | Quux Int | Baz Int
f :: Foo -> Int
f (Bar n) = n
f other =
case other of
Quux n -> 2 * n
Baz n -> 3 * n
g :: Foo -> Int
g foo =
case foo of
Bar n -> n
other ->
case other of
Quux n -> 2 * n
Baz n -> 3 * n
f
和 g
都无法编译,因为 other
上的 case 语句在每个版本中都不是详尽无遗的。
是否有另一种方法来编写这些函数,使得编译器使用静态已知
other
不属于 Bar
变体的事实来证明 case 语句确实是详尽的?
这可以通过多种方式解决(例如,如果在 case 语句中遇到
Bar
,则抛出异常),但我对可以静态检查的东西感兴趣。
可能也是因为您只想进一步处理这两种情况(
Quux
和Baz
)。
因此,您只需添加一个再次递归使用 f 的情况即可。
f :: Foo -> Int
f (Bar n) = n
f other =
case other of
Quux n -> 2 * n
Baz n -> 3 * n
otherwise -> f other