Ни один из трех вариантов не делает одно и то же или не может использоваться во всех ситуациях.
Шаблоны проверяют, какой конструктор использовался для создания заданного значения, и они связывают переменные. Ни если, ни охранники не делают этого. Вы можете использовать их вместо сопоставления с образцом, только если сопоставляете нулевой конструктор (или числовой литерал) типа, реализующего уравнение.
Пример:
foo (Just x) = x+1 -- Can not do this without a pattern match (except by using
-- functions like fromJust that themselves use pattern matches)
foo Nothing = 0 -- You could do this using a pattern guards like
-- foo x | x==Nothing = 0, but that is less readable and less
-- concise than using a plain pattern match
Выкройка охранников позволяет вам проверять другие вещи, кроме равенства. Например. Вы можете проверить, является ли данное число больше нуля. Конечно, вы можете сделать то же самое с if, но охранники шаблонов позволяют вам перейти к следующему шаблону при отказе охранника, что может привести к меньшему количеству повторений, чем при использовании if. Пример:
maybeSqrt (Just x) | x >= 0 = sqrt x
maybeSqrt _ = Nothing
Использование, если это будет выглядеть так (обратите внимание на повторение Nothing):
maybeSqrt (Just x) = if x >= 0 then sqrt x
else Nothing
maybeSqrt _ = Nothing
Наконец, если можно использовать без сопоставления с образцом. Если вы на самом деле не используете сопоставление с образцом для заданного значения, вводя case x of ...
просто для того, чтобы вы могли использовать шаблонные ограждения, мало смысла и менее читабельно и кратко, чем просто использование if.