我如何在 Haskell 中将守卫与模式匹配结合起来?(我可以吗?)

Nik*_*kin 1 haskell pattern-matching

现在我知道,在使用 Haskell 声明函数签名后,我可以使用函数重载进行模式匹配,如下所示:

frog :: Int -> String
frog 1 = "Ribbit"
frog 7 = "Croak"
frog 12 = "Pop!"
frog x = replicate x "Z"
Run Code Online (Sandbox Code Playgroud)

我知道我也可以以类似的方式使用守卫:

frog :: Int -> String
frog x = 
    | x == 1 = "Ribbit"
    | x == 7 = "Croak"
    | x == 12 = "Pop!"
    | otherwise = replicate x "Z"
Run Code Online (Sandbox Code Playgroud)

然而,我宁愿结合使用布尔防护和模式来确定将执行哪个臂的两种方式。类似于这个 Rust 片段的东西:

fn frog(x: u32) -> String {
    match x {
        k if k >= 1000 => todo!()
        k if k >= 100 => todo!()
        k if k >= 10 => todo!()
        9 | 8 | 7 => todo!()
        6 | 5 | 4 => todo!()
        3 => todo!()
        2 => todo!()
        1 => todo!()
        0 => todo!()
    }
}
Run Code Online (Sandbox Code Playgroud)

我想知道在 Haskell 中是否可以做到这一点,如果可以的话该怎么做。先感谢您

Ben*_*son 5

您无法将多个案例与单个模式(9 | 8 | 7来自 Rust 代码的东西)匹配,但您可以直接组合模式和防护:

foo 1 = "one"
foo 2 = "two"
foo k
    | k > 1000 = "greater than 1000"
    | k > 100 = "between 100 and 1000"
    | otherwise = "some other number"
Run Code Online (Sandbox Code Playgroud)

守卫是模式的一部分 - 如果附加到某个案件的守卫没有一个成功,那么控制权就会按照您期望的方式转移到下一个案件。(换句话说,单个模式的防护不必是详尽的。)

bar k | k > 1000 = "greater than 1000"
bar _ = "smaller than 1000"
Run Code Online (Sandbox Code Playgroud)