2009-12-29 2 views
18

나는 데이터를 취하고 같은 데이터 또는 약간 수정 된 버전을 반환하는 함수를 가지고있다.하스켈에서의 평등의 효율성

내 프로그램이 변경된 경우 하나의 작업을 수행하고 변경하지 않은 경우 다른 작업을 수행하려고합니다.

이전에 나는 (Bool,Object) 쌍을 반환했으며 fst을 사용하여 변경되었는지 확인했습니다. 최근에는 객체를 반환하고 동등성을 검사하여 코드를 단순화 할 수 있다고 ==을 통해 알게되었습니다.

하지만 하스켈은 깊은 평등 검사와 "객체 동일성"(즉, 포인터 평등)을 구분하지 않는다는 것을 깨달았습니다. 그렇다면 ==을 사용하는 것이 효율적인지 아닌지 어떻게 알 수 있습니까? 효율성상의 이유로 그것을 피해야합니까, 아니면 컴파일러가 깊은 평등 검사를 수행 할 필요가 없다고 판단 할 수있는 경우가 있습니까?

일반적으로 초기 프로그램을 작성하는 동안 효율성에 대해 너무 걱정하지 않지만 내 모듈의 인터페이스에 영향을 미치므로 너무 많은 코드를 작성하기 전에 바로 얻고 싶습니다. 단순히 코드의 작은 부분만으로 프로그램의 효율성을 떨어 뜨릴 수 있습니다. 또한 GHC에 의존 할 수있는 최적화의 종류에 대해 더 잘 알고 싶습니다.

+12

메모와 마찬가지로 '이저'값이나 이에 상응하는 것이지만 의미가 더 좋은 경우 (예 : '데이터 변경 상태 a = 같은 a | 변경됨 a')가 더 좋은 경우입니다. – Chuck

+0

나쁜 생각은 아닙니다. – Steve

답변

34

불확실한 컴파일러 최적화를 사용하여 상수 시간 동등성과 선형 시간 심도 평등과 같은 중요한 성능 보증을 제공하는 것은 항상 나쁜 생각입니다. 값을 캡슐화하는 새로운 유형과 그 값이 새로운 것인지 여부에 대한 정보를 사용하는 것이 훨씬 낫습니다. 응용 프로그램에 따라이 될 수 있습니다

data Changed a = Changed a | Unchanged a 

또는

data Changed a = Changed a | Unchanged 

우리는 실제로 우리가 코드가 변경 멈출 때까지 최적화를 실행 유지할 수 글래스고 하스켈 컴파일러 내부의 유사한 유형을 사용합니다. 또한 결과가 변하지 않을 때까지 반복적 인 데이터 흐름 분석을 실행합니다.

표기법을 사용하여 몇 가지 간단한 고차 함수를 작성할 수 있도록이 유형을 모나드로 만드는 것이 유용하다는 것을 알았지 만, —은 단지 편리 할뿐입니다.

요약 : 당신은 거기 — 수 없거나하는 다음 릴리스에서 변경 될 수 있습니다 일정 시간의 확인, 그것은 자신 — 가능한 컴파일러 최적화에 의존하지 않는 코드를합니다.

+0

고마워, 그 꽤 구체적인 답변을 느낀다. – Steve

+3

이게 어떻게 모나드처럼 작동하는지 궁금하네요? 두 번째 버전은'Maybe' 모나드처럼 보입니다. 그러나'어쩌면'과 달리, 여기에 마지막으로 변경되지 않은 결과를 원합니다. 단지 나중에 변경되지 않았 음을 알기 만하면됩니다. – yairchu

+0

@yairchu Maybe 모나드와 모호하게 비슷합니다. 모나드 구성에 따라 "변경됨"이있는 경우 결과는 "변경됨"이고, 그렇지 않으면 "변경되지 않음"입니다. –

1

저는 여전히 상대방의 젤러 멍청이입니다. 그래서 소금물로 제 대답을 듣고 제 대답이 직접적이지 않으면 용서해주세요!

하스켈에서 연산자는 특별한 것이 아니며 중온 함수입니다.

표준 서곡에서 definition of the equality operator을 직접 볼 수 있습니다.

물론 정의 된 데이터 유형으로 작업 할 수 있도록 오버로드 될 수 있습니다.하지만 오버로드를 수행하면 구현이 얼마나 효율적인지 알 수 있습니다.

Hoogle을 사용하여 원하는 기능 정의를 찾을 수 있다는 것을 알고 있으면 도움이 될 수 있습니다. 그것이 평등 연산자의 정의를 찾은 방법입니다.

+0

이 게시물을 볼 가치가 너무 : http://stackoverflow.com/questions/1717553/pointer-equality-in-haskell – nont

4

파생 된 (==)은 항상 깊은 비교입니다. 귀하의 질문은 haskell-cafe의 discussed입니다.