1

서두 에서 :foldl1이 (==) 연산자를 적용하지 못하는 이유는 무엇입니까?

foldl1 : 그것은 리스트의 제 2 개 항목을 취해 그 에 함수를 적용하고 있으므로 이 결과 세 번째 인자 및 와 기능 피드 에.

왜 이런 식으로 쓸 수 없습니까?

foldl1 (==) [6, 6, 6] 
foldl1 (\x y -> x == y) [6, 6, 6] 
+3

그냥 직감하지만, 처음 두에 항등 연산자를 적용하는 부울을 산출 : 여기 –

답변

2

EDIT : Antal이 내 추론이 잘못되었다고 지적합니다. 여기에 실제 추론을하는 주석의 관련 부분이 있습니다 (나는이 말을 그대로 받아 들일 수는 없지만이 대답은 받아 들일 수 없으므로 삭제할 수 없습니다) :

이것이 작동하지 않는 이유는 foldl1의 값은 (a -> a -> a) -> [a] -> a이지만 (==)의 유형은 Num a => a -> a -> Bool입니다. BoolNum이 아니기 때문에 (==) 유형이 a -> a -> a과 일치하지 않으므로 foldl1의 적용이 거부됩니다. 그것이 받아 들여 졌다면, 당신은 True == 6을하려고하는 상황에 처하게 될 것입니다. 그러나 타입 시스템은 당신을 처음부터 멀리하게하지 않습니다.

원래 대답 (잘못된 후자의 논리는) :

==Int의을하고 Bool를 반환합니다. 첫 번째 반복 후에 예제 목록은 [True, 6]이됩니다. 그런 다음 실패한 True6과 비교합니다.

+1

첫 번째 문장은 정확하지만, 하스켈에서는 True가 1로 캐스트되지 않습니다! – dvitek

+0

@marcog : 감사합니다. 완벽한 의미입니다. 부끄러움에 대해 생각하지 마라! :) – gremo

+0

@drvitek 감사합니다. 나의 실제적인 haskell은 강하지 않다. – marcog

5

당신이 목록의 모든 요소가 동일한 경우는 확인하려는 경우, 빠른 해결책은

allEqual [] = True --(edit: this case is not necessary as pointed out by sepp2k) 
allEqual xs = all (== head xs) xs 

누군가가이 일을 더 우아한 방법을 쓸 것입니다, 나는 확신하지만이 수리 할 수있다 .

수정 : 제안 사항에 대해 sepp2k에게 감사드립니다. 당신이 배를 사용하려면

+1

어쨌든'및 []'가 참이므로 첫 번째 경우는 필요 없습니다. 또한'및. map'은'all'입니다. – sepp2k

+1

sepp2k : 먼저 댓글을 보지 않고서야 깨달았습니다. 나는 우리가 같은 것을 생각하고 있었다고 생각한다. 그러나 첫 번째 경우는 필요 없다는 것을 깨닫는 것이 영리합니다. 나는이 경우에 '머리'가 실패 할 것이라고 생각하고 있었다. – dvitek

+2

평가 되었다면 실패했을 것이다. 그러나'xs'가 비어 있다면,'all'은 절대로 함수를 호출하지 않으므로'head'를 평가할 필요가 없습니다. – sepp2k

0

,이 수정 제안 :

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) 
+0

난독 화를 위해'allEqual xs = foldl '(flip $ (&&). (== head xs)) True xs'라고 쓸 수 있습니다. – Landei

1

다른 버전입니다. 부울을 정수와 비교하는 것이 합리적이라고는 생각하지 않습니다.
+1

당신의 답에 영감을 얻어이 또한 있습니다 :'allEqual xs = tail xs == init xs' –

+0

** ** 멋집니다. – Landei

+0

@ Dan : 꼬리 대신에 드롭 1을 사용하고 싶을 수도 있습니다. 따라서 빈 목록에서도 사용할 수 있습니다. – Axman6

관련 문제