목록의 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)
제 생각에는 첫 번째 기능이 가장 간결하기 때문에 최상의 구현입니다. 그러나 다른 두 가지 구현에 대해 선호하는 것이 있습니까? 그리고 더 나아가 가드, if-then-else 문 및 케이스 사용 중에서 어떻게 선택 하시겠습니까?
답변
기술적 관점에서 세 가지 버전은 모두 동일합니다.
즉, 스타일에 대한 제 경험 법칙은 마치 영어처럼 읽을 수 있다면 ( |
“언제”, | 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. 스타일 팁으로 / 뒤의 내용 이 한 줄에 너무 길거나 다른 이유로 더 많은 줄을 사용 =
하는 |
경우 항상 a 뒤 또는 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)
답변
이것이 명시 적으로 재귀 함수에 대한 스타일에 대한 질문이라는 것을 알고 있지만 가장 좋은 스타일은 기존 재귀 함수를 대신 재사용하는 방법을 찾는 것입니다.
nthElement xs n = guard (n > 0) >> listToMaybe (drop (n-1) xs)
답변
이것은 주문의 문제이지만 매우 읽기 쉽고 경비원과 동일한 구조를 가지고 있다고 생각합니다.
nthElement :: [a] -> Int -> Maybe a
nthElement [] a = Nothing
nthElement (x:xs) a = if a < 1 then Nothing else
if a == 1 then Just x
else nthElement xs (a-1)
마지막 다른 것은 필요하지 않으며 다른 가능성이 없기 때문에 함수도 놓친 경우 “마지막 수단”이 있어야합니다.