Ответ 1
С технической точки зрения все три версии эквивалентны.
Как говорится, мое правило для стилей заключается в том, что если вы можете прочитать его, как если бы он был английским (читайте |
как "когда", | otherwise
как "в противном случае" и =
как "есть", или "быть" ), вы, вероятно, делаете что-то правильно.
if..then..else
- это когда у вас есть одно двоичное условие или одно решение, которое вам нужно сделать. Вложенные if..then..else
-выражения очень редко встречаются в Haskell, и охранники должны использоваться почти всегда.
let absOfN =
if n < 0 -- Single binary expression
then -n
else n
Каждое выражение if..then..else
может быть заменено на охрану, если оно находится на верхнем уровне функции, и это обычно должно быть предпочтительным, поскольку вы можете добавить больше случаев более легко:
abs n
| n < 0 = -n
| otherwise = n
case..of
- это когда у вас несколько путей кода, и каждый путь кода управляется
структуру значения, то есть посредством сопоставления с образцом. Вы очень редко встречаетесь на True
и False
.
case mapping of
Constant v -> const v
Function f -> map f
Гвардии дополняют выражения case..of
, что означает, что если вам нужно принимать сложные решения в зависимости от значения, сначала принимайте решения в зависимости от структуры вашего ввода, а затем принимайте решения о значениях в структуре.
handle ExitSuccess = return ()
handle (ExitFailure code)
| code < 0 = putStrLn . ("internal error " ++) . show . abs $ code
| otherwise = putStrLn . ("user error " ++) . show $ code
BTW. В качестве подсказки стиля всегда создавайте новую строку после =
или до |
, если материал после =
/|
слишком длинный для одной строки, или использует больше строк по другой причине:
-- NO!
nthElement (x:xs) a | a <= 0 = Nothing
| a == 1 = Just x
| a > 1 = nthElement xs (a-1)
-- Much more compact! Look at those spaces we didn't waste!
nthElement (x:xs) a
| a <= 0 = Nothing
| a == 1 = Just x
| otherwise = nthElement xs (a-1)