Подтвердить что ты не робот

Каков предпочтительный метод написания "охранников"?

Ive создал функцию, в которой я могу использовать (насколько мне известно) выражения case или guard.

foo a b c = case a of 1 -> [...]
                      2 -> [...]
                      3 -> [...] 
                      [...]
                      otherwise -> error "..."

или

foo a b c | a == 1 = [...]
          | a == 2 = [...]
          | a == 3 = [...] 
          | [...]
          | otherwise = error "..."

Итак, возникает вопрос: какой из этих 2 (случай или страж) является "лучшим" кодированием? Оба в основном одинаковы?

4b9b3361

Ответ 1

Первый считается лучшим стилем по двум причинам.

Прежде всего: многие люди скажут, что это выглядит лучше, так как вам не нужно набирать все ==. Разумеется, это очень субъективная причина. Кроме того, обычно вы даже не вводите новый оператор case, а просто сопоставляете аргументы в списке аргументов функции следующим образом:

foo 1 b c = ... -- etc
...
foo _ b c = ... -- for the "otherwise" part

Это делает код еще более компактным и читаемым, что многим нравится.

Во-вторых, на самом деле существует семантическая разница. Представьте, что у вас есть такой тип данных, как это:

data Cake = Apple | Cheese | Cream

Если вы используете первый метод, вы сопоставляетесь с конструкторами в выражении case..of:

case a of
  Apple -> "fruit"
  _     -> "not fruit"

Однако, если вы попытаетесь сделать какое-то охраняемое выражение, например:

| a == Apple = "fruit"
| otherwise  = "not fruit"

... на самом деле это не будет работать, потому что тип Cake не имеет экземпляра Eq, поэтому вы не можете использовать == для сравнения двух значений. Представление экземпляра Eqderiving (Eq) после определения данных) не всегда требуется, поэтому не делать этого в этом случае может быть значительным.

Ответ 2

Когда охранник может быть переписан как (беззащитный) case-statement по одному из параметров, он не является актуальным. То есть вы можете просто написать его как:

foo 1 b c = [...]
foo 2 b c = [...]
foo 3 b c = [...]
[...]

Каков предпочтительный способ написать его. Вы должны использовать охранники, когда условие, которое вы хотите, не может быть выражено в виде шаблона. И вы должны использовать case-statement, когда вам нужно сопоставить что-то, отличное от одного из параметров.