Jas*_* Tu 98 haskell if-statement case
我有三个函数可以找到列表的第n个元素:
nthElement :: [a] -> Int -> Maybe a
nthElement [] a = Nothing
nthElement (x:xs) a | a <= 0 = Nothing
| a == 1 = Just x
| a > 1 = nthElement xs (a-1)
nthElementIf :: [a] -> Int -> Maybe a
nthElementIf [] a = Nothing
nthElementIf (x:xs) a = if a <= 1
then if a <= 0
then Nothing
else Just x -- a == 1
else nthElementIf xs (a-1)
nthElementCases :: [a] -> Int -> Maybe a
nthElementCases [] a = Nothing
nthElementCases (x:xs) a = case a <= 0 of
True -> Nothing
False -> case a == 1 of
True -> Just x
False -> nthElementCases xs (a-1)
Run Code Online (Sandbox Code Playgroud)
在我看来,第一个功能是最好的实现,因为它是最简洁的.但是有没有其他两个实现可以使它们更可取?通过扩展,您如何选择使用警卫,if-then-else语句和案例?
dfl*_*str 116
从技术角度来看,所有三个版本都是等效的.
话虽这么说,我对风格的经验法则是,如果你能把它看成是英文(读|作"当",| otherwise"不然"和="是"或"是"),你可能正在做某事对.
if..then..else是因为你有一个二元条件,或者你需要做出一个单一的决定.嵌套 - if..then..else表达式在Haskell中非常罕见,并且几乎总是应该使用守卫.
let absOfN =
if n < 0 -- Single binary expression
then -n
else n
Run Code Online (Sandbox Code Playgroud)
if..then..else如果它位于函数的顶层,那么每个表达式都可以被一个守护者替换,这通常应该是首选的,因为你可以更容易地添加更多的情况:
abs n
| n < 0 = -n
| otherwise = n
Run Code Online (Sandbox Code Playgroud)
case..of当你有多个代码路径时,每个代码路径都由一个值的结构引导
,即通过模式匹配.你很少匹配True和False.
case mapping of
Constant v -> const v
Function f -> map f
Run Code Online (Sandbox Code Playgroud)
防护补充case..of表达式,这意味着如果您需要根据值做出复杂的决策,首先根据输入的结构做出决策,然后对结构中的值做出决策.
handle ExitSuccess = return ()
handle (ExitFailure code)
| code < 0 = putStrLn . ("internal error " ++) . show . abs $ code
| otherwise = putStrLn . ("user error " ++) . show $ code
Run Code Online (Sandbox Code Playgroud)
BTW.作为样式提示,总是在a之后=或之前创建一个换行符|如果=/ 之后的东西|对于一行太长,或者由于某些其他原因使用更多行:
-- 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)
Run Code Online (Sandbox Code Playgroud)
Dan*_*ner 22
我知道这是关于显式递归函数的样式的问题,但我建议最好的样式是找到一种方法来重用现有的递归函数.
nthElement xs n = guard (n > 0) >> listToMaybe (drop (n-1) xs)
Run Code Online (Sandbox Code Playgroud)
小智 5
虽然所有三个实现都产生正确的结果,但 GHC(截至 2021 年)抱怨模式匹配不是详尽的 \xe2\x80\x93 ,因为可能的模式隐藏在 Guards/if/case 后面,这是正确的。考虑这个实现,它比它们三个更简洁,而且避免了非详尽模式警告:
\nnthElement :: [a] -> Int -> Maybe a\nnthElement (x:_) 1 = Just x\nnthElement (_:xs) i = nthElement xs (i - 1)\nnthElement _ _ = Nothing -- index is out of bounds\nRun Code Online (Sandbox Code Playgroud)\n最后一个模式匹配所有内容,因此需要低于前两个模式可能成功的匹配。
\n| 归档时间: |
|
| 查看次数: |
59354 次 |
| 最近记录: |