2012-10-04 3 views
3

하스켈을 배우고 있습니다. 내가 올바르게 이해한다면, 하스켈의 간단한 함수는 항상 명확하게 투명합니다. 나는 그것의 산출물이 전달 된 인자들에만 의존한다는 것을 의미한다고 생각했다.외부 범위에 정의 된 함수를 사용하면 참조 투명성이 깨지지 않는 이유는 무엇입니까?

그러나 함수 f은 외부 범위에 정의 된 g이라는 다른 함수를 호출 할 수 있습니다. 따라서이 의미에서 f의 반환 값은 g의 정의에 따라 다릅니다. 그리고 g 함수는 적어도 명시 적으로 매개 변수로 f에 전달되지 않습니다. 참조 투명성이 깨지지 않습니까?

답변

6

참고 투명성

f s = "Hello " ++ g s 
g s = s ++ "!" 

그것은 당신이 f의 의미를 변경하지 않고 fg 인라인 수 있음을 의미

f s = "Hello " ++ h s 
    where h s = s ++ "!" 
g s = s ++ "!" 

f s = "Hello " ++ s ++ "!" 
g s = s ++ "!" 

에서 구별 할 수 있음을 의미합니다.

f의 의미를 바꾸려면 어떻게 든 g을 변경해야합니다. 방법?

+1

런타임에 'g'를 재정의 할 수 없습니까? 미안 하스켈을 아직 알지 못한다. – max

+17

런타임시 아무것도 재정의 할 수 없습니다. – augustss

8

키는 불변입니다.

기본적으로 가변성을 허용하는 언어 인 Javascript와의 비교를 통해이 지점을 설명하겠습니다. 다음 코드를 고려하십시오

f = function(x) { 
    return x; 
} 

g = function(y) { 
    f = function(x) { 
     return x+y; 
    } 
} 

이제 참조 투명성을 깰 수 있습니다 당신은 자신의 가치와 f에 전화를 대체 할 수 있기 때문에 우리는 참조 투명성이없는

f(1) -- returns 1 
g(10) 
f(1) -- returns 11 

. 예를 들어, 코드

console.log(f(1)) 
g(10) 
console.log(f(1)) 

당신은 점점 가치 (1)와 f(1)에 모두 전화를 대체 할 수 있다는 상상

console.log(1) 
g(10) 
console.log(1) 

즉 콘솔에 1를 출력 코드의 조각 두번. 그러나 실제로는 원래 코드를 실행하면 1을 출력하고 g(10)을 호출하기 때문에 11을 출력합니다.

하스켈에서는 모든 값을 변경할 수 없기 때문에 불가능합니다. 즉, 하스켈에서는 범위 밖에있는 다른 함수의 값을 수정하는 함수 g을 작성할 수 없습니다. 하스켈에서는 코드를 깨뜨리지 않고 항상 함수 호출을 값으로 대체 할 수 있습니다.

4

g이 매개 변수로 전달되지 않으면 "최상위 수준 선언"입니다. 그리고 이러한 선언은 런타임에 변경 될 수 없습니다. 프로그램을 다시 컴파일하는 경우에만 변경할 수 있습니다.

따라서 함수가 런타임에 다른 결과를 산출 할 수있는 유일한 방법은 선언 된 입력이 변경되는 경우입니다. 그것은 여러 다른 것들에 "의존"하지만, 런타임에 이러한 다른 것들은 변할 수 없습니다.