서두 에서 :foldl1이 (==) 연산자를 적용하지 못하는 이유는 무엇입니까?
foldl1 : 그것은 리스트의 제 2 개 항목을 취해 그 에 함수를 적용하고 있으므로 이 결과 세 번째 인자 및 와 기능 피드 에.
왜 이런 식으로 쓸 수 없습니까?
foldl1 (==) [6, 6, 6]
foldl1 (\x y -> x == y) [6, 6, 6]
서두 에서 :foldl1이 (==) 연산자를 적용하지 못하는 이유는 무엇입니까?
foldl1 : 그것은 리스트의 제 2 개 항목을 취해 그 에 함수를 적용하고 있으므로 이 결과 세 번째 인자 및 와 기능 피드 에.
왜 이런 식으로 쓸 수 없습니까?
foldl1 (==) [6, 6, 6]
foldl1 (\x y -> x == y) [6, 6, 6]
EDIT : Antal이 내 추론이 잘못되었다고 지적합니다. 여기에 실제 추론을하는 주석의 관련 부분이 있습니다 (나는이 말을 그대로 받아 들일 수는 없지만이 대답은 받아 들일 수 없으므로 삭제할 수 없습니다) :
이것이 작동하지 않는 이유는 foldl1
의 값은 (a -> a -> a) -> [a] -> a
이지만 (==)
의 유형은 Num a => a -> a -> Bool
입니다. Bool
이 Num
이 아니기 때문에 (==)
유형이 a -> a -> a
과 일치하지 않으므로 foldl1
의 적용이 거부됩니다. 그것이 받아 들여 졌다면, 당신은 True == 6
을하려고하는 상황에 처하게 될 것입니다. 그러나 타입 시스템은 당신을 처음부터 멀리하게하지 않습니다.
원래 대답 (잘못된 후자의 논리는) :
==
두 Int
의을하고 Bool
를 반환합니다. 첫 번째 반복 후에 예제 목록은 [True, 6]
이됩니다. 그런 다음 실패한 True
을 6
과 비교합니다.
당신이 목록의 모든 요소가 동일한 경우는 확인하려는 경우, 빠른 해결책은
allEqual [] = True --(edit: this case is not necessary as pointed out by sepp2k)
allEqual xs = all (== head xs) xs
누군가가이 일을 더 우아한 방법을 쓸 것입니다, 나는 확신하지만이 수리 할 수있다 .
수정 : 제안 사항에 대해 sepp2k에게 감사드립니다. 당신이 배를 사용하려면
어쨌든'및 []'가 참이므로 첫 번째 경우는 필요 없습니다. 또한'및. map'은'all'입니다. – sepp2k
sepp2k : 먼저 댓글을 보지 않고서야 깨달았습니다. 나는 우리가 같은 것을 생각하고 있었다고 생각한다. 그러나 첫 번째 경우는 필요 없다는 것을 깨닫는 것이 영리합니다. 나는이 경우에 '머리'가 실패 할 것이라고 생각하고 있었다. – dvitek
평가 되었다면 실패했을 것이다. 그러나'xs'가 비어 있다면,'all'은 절대로 함수를 호출하지 않으므로'head'를 평가할 필요가 없습니다. – sepp2k
,이 수정 제안 :
는allEqual xs = foldr (\x acc -> x == head xs && acc) True xs
이 이미 제안 all
접근 방식과 매우 유사하다. 이 값과 all
방법은 모두 무한한 목록에서 작동 할 수 있습니다 (대답이 False
인 경우). 당신이 엄격한 왼쪽 배에서 더 나은 성능을 얻을 수 있습니다 매우 드문 경우 매우 긴 유한 목록에 대한
:
allEqual xs = foldl' (\acc x -> acc && x == head xs) True xs
을하지만 바로 배 (이 구현) 때문에,이 문제에 대한 일반적으로 더 낫다 length $ takeWhile (== head xs) xs
과 같은 수의 폴딩 단계 만 수행합니다. 왼쪽 접기는 매번 length xs
폴딩 단계를 수행합니다.
allEqual xs = and $ zipWith (==) xs (tail xs)
난독 화를 위해'allEqual xs = foldl '(flip $ (&&). (== head xs)) True xs'라고 쓸 수 있습니다. – Landei
그냥 직감하지만, 처음 두에 항등 연산자를 적용하는 부울을 산출 : 여기 –