As others mentioned, there is no difference in the generated code as the former approach desugars to the latter approach, however I can point out some other considerations that may help you choose one or the other to use:
- The former approach looks prettier in some circumstances (although I personally think that once you have lots of cases it is distracting)
- The former approach makes it slightly more difficult to refactor the name. Using the case statement the name of the function only appears once.
- Case statements can be used anywhere in your code and can be used anonymously. The former approach requires using a
let or where block to define pattern-matching functions within a function.
However, there are no cases where you can't translate one into the other. It's entirely a matter of coding style.
ifand guards aren't good options for this, but the two you're asking about are indeed equivalent – as a matter of fact, GHC will pack different patterns for a function in acasestatement in the first compilation step anyway.