문제

나는 Haskell 코드를 가지고 있습니다. 하다 무한 목록에서 올바르게 작동하지만 이해가 안 돼요 성공적으로 할 수 있습니다.(무한 목록을 처리하지 않는 원래 코드를 수정하여 온라인에서 다른 코드의 내용을 통합했는데 갑자기 작동하는 것을 보았지만 이유는 알 수 없습니다.)

myAny :: (a -> Bool) -> [a] -> Bool
myAny p list = foldr step False list
   where
      step item acc = p item || acc

제가 Foldr에 대해 이해한 바는 목록의 모든 항목을 반복한다는 것입니다(아마도 이해가 불완전할 수도 있습니다).그렇다면 "단계" 기능이 어떻게 표현되는지는 중요하지 않습니다.코드는 무한 루프를 처리할 수 없어야 합니다.

그러나 다음은 작동합니다.

*Main Data.List> myAny even [1..]
True

제가 이해하도록 도와주세요:왜??

도움이 되었습니까?

해결책

Haskell이 여러분의 표현식을 어떻게 평가하는지 머릿속으로 조금 추적해 봅시다.각 줄에서 같음을 같음으로 대체하면 표현식은 매우 빠르게 True로 평가됩니다.

myAny even [1..]
foldr step False [1..]
step 1 (foldr step False [2..])
even 1 || (foldr step False [2..])
False  || (foldr step False [2..])
foldr step False [2..]
step 2 (foldr step False [3..])
even 2 || (foldr step False [3..])
True   || (foldr step false [3..])
True

이것은 작동합니다. acc 평가되지 않은 썽크(게으른 평가)로 전달될 뿐만 아니라 || 기능이 엄격하다 첫 번째 논쟁.

그래서 이것은 종료됩니다:

True || and (repeat True)

하지만 다음은 그렇지 않습니다.

and (repeat True) || True

||의 정의를보십시오 이것이 왜 그런지 확인하기 위해 :

True  || _ =  True
False || x =  x

다른 팁

Foldr에 대한 나의 이해는 그것이 목록의 모든 항목을 통해 루프한다는 것입니다 (그리고 아마도 이해가 불완전합니다).

foldr (같지 않은 foldl) 목록의 모든 항목을 반복할 필요는 없습니다.방법을 살펴보는 것이 유익합니다. foldr 정의되어 있습니다.

foldr f z []     = z
foldr f z (x:xs) = f x (foldr f z xs)

전화를 걸 때 foldr 평가되면 함수 호출을 강제로 평가하게 됩니다. f.그러나 재귀 호출이 foldr 함수에 대한 인수에 포함됩니다. f.해당 재귀 호출은 다음과 같은 경우 평가되지 않습니다. f 두 번째 인수를 평가하지 않습니다.

여기서 중요한 점은 Haskell이 엄격하지 않은 언어라는 것입니다."비엄격"은 엄격하지 않은 함수를 허용한다는 의미이며, 이는 함수 매개변수가 사용되기 전에 완전히 평가되지 않을 수 있음을 의미합니다.이는 분명히 "결과가 필요할 때까지 계산을 지연시키는 기술"인 지연 평가를 허용합니다.

에서 시작하다 이 위키 기사

나는 Haskell을 모르지만 귀하의 경우 게으른 평가 때문에 작동하는 것 같습니다.무한히 긴 목록으로 작업할 수 있으므로 목록에 액세스하면 필요할 때마다 결과가 계산됩니다.

보다 http://en.wikipedia.org/wiki/Lazy_evaluation

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top