我有一个包含相对较多模式的case
表达式:
case x of
... -> ...
... -> ...
... -> ...
... -> ...
...
_ -> ...
其中一个箱子有个守卫:
case x of
... -> ...
... -> ...
... | condition -> ...
-- If condition is false, fall through to “Rest”.
-- Rest:
... -> ...
... -> ...
...
_ -> ...
如果后卫不匹配,我们就继续处理剩下的案子,没问题。但是现在我需要对条件进行单调测试,所以我这样做了:
case x of
... -> ...
... -> ...
... -> do
condition <- action
if condition
then ...
else ... -- How to fall through?
-- Rest:
... -> ...
... -> ...
...
_ -> ...
然而,我想我犯了一个错误。似乎没有一种方法可以让else
分支继续处理其余的情况,而不复制这些分支或将它们分解到一个函数中。无论哪种方式都会扰乱穷举检查:如果我想在guard后面添加一个case,编译器不知道匹配是否是穷举的。
如何更改此函数,或参数化/包装数据类型,以使用一元保护进行穷举检查?
发布于 2016-07-18 18:14:14
一个简单的选择是获取case
代码块的后半部分,并将其放入一个单独的函数中。
case (x, y) of
(Foo ..., Foo ...) -> ...
x@(Bar ..., Bar ...) -> do
condition <- action
if condition
then ...
else rest x
x -> rest x
rest (Baz ..., ...) = ...
rest (Var ..., ...) = ...
...
rest _ = undefined
在rest
的失败案例中使用undefined
来捕获您认为应该在原始case
块的前半部分中匹配的模式,这有点不令人满意。如果您设法违反了前提条件( (Foo, Foo)
等不匹配),那么您将得到一个运行时错误。
发布于 2016-07-18 18:33:33
我不喜欢下面的方法,但无论如何我都会分享它:
fix (\proceed b -> case (x, y, b) of
(Foo ..., Foo ..., False) -> ...
(Bar ..., Bar ..., False) -> do
condition <- action
if condition
then ...
else proceed True
(Baz ..., ..., _) -> ...
(Var ..., ..., _) -> ...
...
) False
附加标志b
最初为false,因此会考虑所有分支。一旦我们执行proceed
,我们将其设置为true,这样就会跳过第一个分支。
根据实际的模式,可能会或可能不会静态地被发现是详尽的。
发布于 2018-04-15 06:05:50
我最终做的是使用配备了Maybe
的monad堆栈,并在一系列操作上用asum
替换case
,遵循以下结构:
asum
[ do
pattern1 <- pure input -- failed pattern matches fall through
body1
, do
pattern2 <- pure input
body2
, do
pattern1 <- pure input
guard condition -- guards also fall through
body3
, ...
]
正如我最近在this answer中对其他人的问题所描述的那样。不幸的是,这不允许进行详尽的检查。
https://stackoverflow.com/questions/38442963
复制相似问题