2011-12-31 1 views
9

난 그냥 하스켈을 배우는 튜토리얼 사이트에서 두 프로그램을 작성하고, 같은 어디서이 두 프로그램은 상당히 동등한 생각

maximumwhere :: (Ord a) => [a] -> a 
maximumwhere [] = error "empty" 
maximumwhere [x] = x 
maximumwhere (x:xs) = if x > maximum' then x else maximum' where maximum' = maximumwhere xs 

maximumnowhere :: (Ord a) => [a] -> a 
maximumnowhere [] = error "empty" 
maximumnowhere [x] = x 
maximumnowhere (x:xs) = if x > maximumnowhere xs then x else maximumnowhere xs 

있고

바인딩, 왜냐하면 바인딩은 변수를 내용으로 대체하기 때문입니다. 하지만 ghci에서 실행할 때 첫 번째 방법은 후자보다 느린 편이었습니다. 특히 길이가 25 이상인 배열의 경우에는 더욱 그렇습니다. 아마도 바인딩을 사용하면 성능 차이가 커질 수 있지만 그 이유는 모르겠습니다. 아무도 나를 위해 그것을 설명 할 수 있습니까?

+1

첫 번째 것은'maximumnowhere xs' (if 조건문과 else 경우 모두에 사용됨)의 평가를 공유하지 않습니다. 공유하고 싶다면 두 번째 버전에 따라 스스로해야합니다. –

+3

추가 정보를 추가하면 GHC는 일반적으로 공통 하위 표현식 제거를 수행하지 않습니다 (두 버전이 동일하게 수행하게됩니다). 이는 CSE가 게으른 언어로 공간 누수를 유발할 수 있기 때문입니다. GHC FAQ - http://www.haskell.org/haskellwiki/GHC:FAQ#Does_GHC_do_common_subexpression_elimination.3F –

+5

ghci를 성능 측정에 사용하는 이유는 무엇입니까? 테스트 할 수있는 최적화 컴파일러가 있습니다 .. –

답변

14

아니요, 해당하지 않습니다. letwheresharing을 도입합니다. 즉,이 값은 한 번만 평가됩니다. 컴파일러는 당신이 말하지 않는 한 일반적으로 두 개의 동일한 표현식의 결과를 공유하지 않을 것입니다. 왜냐하면 일반적으로 이것을 수행하는 시공간 트레이드 오프가 유익한 것인지 아닌지를 스스로 알 수 없기 때문입니다. 제 만 반복 하나씩, 즉 O (N) 않지만

따라서 첫 프로그램은 그것 O (2^N)하게 반복 당 두 재귀 호출 할 것이다. 이것들의 차이는 엄청납니다. 두 번째는 25

을 수행하는 동안에서 N = 25, 33 백만 재귀 호출의 첫 번째 프로그램 결과에 따라서 이야기의 교훈은 당신이 공유하고 싶은 경우에, 당신은 let를 사용하여 요청할 필요가있다 또는 where.

+5

+1 좋은 답변입니다. 하스켈의 순결로 인해, 우리는 종종 등식 추론을 강조하지만, 수행자 하스켈에게는 컴파일러가 어떤 가정을하고 있는지를 아는 것이 중요합니다. (이 경우 GHC는 일반적으로 프로그래머가 명시 적으로 공유를 나타낼 것으로 기대합니다.) –