Home > Net >  How can i combine guards with pattern matching in Haskell? (And can I at all?)
How can i combine guards with pattern matching in Haskell? (And can I at all?)

Time:09-08

Now I know that after I declare function signature with Haskell, I can do pattern matching with function overloading like so:

frog :: Int -> String
frog 1 = "Ribbit"
frog 7 = "Croak"
frog 12 = "Pop!"
frog x = replicate x "Z"

I know I also can use guards in a similar fashion:

frog :: Int -> String
frog x = 
    | x == 1 = "Ribbit"
    | x == 7 = "Croak"
    | x == 12 = "Pop!"
    | otherwise = replicate x "Z"

However I would rather prefer to combine the two ways using both a Boolean guard and a pattern to determine which arm would be executed. Something similar to this rust snippet:

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!()
    }
}

I would like to know if that's possible to do in Haskell, and if so how to do it. Thank you in advance

CodePudding user response:

You can't match multiple cases with a single pattern (the 9 | 8 | 7 thing), but you can straightforwardly combine patterns and guards:

foo 1 = "one"
foo 2 = "two"
foo k
    | k > 1000 = "greater than 1000"
    | k > 100 = "between 100 and 1000"
    | otherwise = "some other number"

The guards are part of the pattern - if none of the guards attached to a case succeed, then control falls through to the next case in the way you'd expect. (To put it another way, a single pattern's guards don't have to be exhaustive.)

bar k | k > 1000 = "greater than 1000"
bar _ = "smaller than 1000"
  • Related