在 Haskell 中合并多个案例

问题描述

使用 case _ of 这样的语法:

fun a b c =
    case (a,b,c) of
        (Just True,Just _,_) -> foo
        (Just True,_,Just _) -> foo
        _                      -> bar

我可以合并前两个条件并避免重复 foo 吗?

或者,有没有其他(更干净的)方式来表达我想运行 foo 当且仅当 aJust True 并且 b 或 {{ 1}} 不是 c

解决方法

你可以这样做:

fun a b c = case (a,b <|> c) of
    (Just True,Just _) -> foo
    _ -> bar

当然,这只是在 (<|>) 中隐藏了额外的匹配项,但您必须向吹笛者支付一些时间。

如果 bc 的类型不同,您可以使它们使用名称错误的 void

,

让我用一个“无聊”的替代方案来补充其他答案:

fun a b c = let
   foo' = foo
   in case (a,b,c) of
      (Just True,Just _,_) -> foo'
      (Just True,_,Just _) -> foo'
      _                      -> bar

这可能会也可能不会回答预期的问题,具体取决于实际目标。

如果目标是避免在 case 中编写两个模式,这当然达不到目标。

如果相反的目标是避免重复 foo,这可能是一个很长的表达式(例如,某些 monad 中的长 do 块),则通过为长表达式。

,

不知道这是否看起来更干净,但您也可以使用老朋友if

fun a b c =
   if a == Just True && (isJust b || isJust c) 
      then foo
      else bar

或使用守卫

fun a b c =
   case a of
       Just True | isJust b || isJust c -> foo
       _ -> bar

无大小写:

fun (Just True) b c | isJust b || isJust c = foo
fun _ _ _ = bar

所有都使用 isJust 并且正如 Daniel 指出的那样,它们也会给吹笛者它应得的(模式匹配)。