С технической точки зрения все три версии эквивалентны.
При этом мое эмпирическое правило заключается в том, что если вы можете читать его, как если бы он был английским (читайте |
как "когда", | 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
Guards дополняет case..of
выражений, что означает, что если вам нужно принимать сложные решения в зависимости от значения, first принимает решения в зависимости от структуры вашего ввода, а затем make решения о значениях в структуре.
handle ExitSuccess = return ()
handle (ExitFailure code)
| code < 0 = putStrLn . ("internal error " ++) . show . abs $ code
| otherwise = putStrLn . ("user error " ++) . show $ code
Кстати. В качестве подсказки стиля всегда делайте новую строку после =
или перед |
, если материал после =
/ |
слишком длинный для одной строки, или использует больше строк по какой-то другой причине:
-- 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)