2013-07-11 5 views
2

저는 하스켈을 가르치고 있습니다. 그리고 저는 이름 선언에 대해 저에게 질문을 제기하는 "뒤집기"함수의 두 가지 구현을 보았습니다.하스켈 이름 선언 규칙

이이 같은 일을 : 내가 기대하는 것처럼

flip'' :: (a -> b -> c) -> b -> a -> c 
flip'' f y x = f x y 

flip' :: (a -> b -> c) -> (b -> a -> c) 
flip' f = g 
    where g x y = f y x 

첫 번째 예입니다. 두 번째 예에서는 x 또는 y를 아직 선언하지 않은 경우 g x y = f y x을 쓸 수있는 이유가 무엇인지 혼동합니다. 나는 게으른 평가가 필요할 때까지 평가되지 않는다는 것을 이해하지만 적어도 컴파일러가 선언을 원할 것으로 기대했다.

그것은 ... 심지어 타입 서명없이 컴파일이 잘 작동 :

flip' f = g 
    where g x y = f y x 

그래서 x와 y 그냥 완전히 지정되지 않은 변수? 아니면 다른 일이 있습니까? 왜 우리가 이것을 할 수 있습니까?

+1

x와 y는 여러 형태로 입력 된 변수입니다. 특별한 방식으로 사용되지 않으므로 유형은 무엇이든 될 수 있습니다. – AndrewC

+0

@AndrewC 감사합니다. - 그것에 대해 생각해 볼 수있는 유용한 방법입니다. 그리고 내 추가 연구를위한 훌륭한 키워드입니다. – Stephen

답변

3

이 아직 x 또는 y로 선언되지 않은 경우 g x y = f y x로 쓸 수있는 이유가 혼동 스럽습니다.

g, x 및 y는 등호 왼쪽에 나타나므로 실제로 선언됩니다. where에는 첨부 된 코드의 로컬 범위가 있습니다. 코드는 이렇게 기록 될 수 있습니다 : 영어

flip f = let g x y = f y x in g 

: g하자 x와 y라는 두 개의 인수 함수가 될 ....

+1

고마워, 나는 이것이 내게 요약된다고 생각한다. "g, x와 y는 등호 왼쪽에 나타나므로 사실 그들은 선언되었다." 나는 그들이 등호 부호의 양쪽에 있기 때문에 나는 혼란 스러웠다 고 생각한다. 보통 x = x + 1을 사용하여 x를 선언하면 명령형 언어로 문제가 생길 것이다. (언어에 따라 실패하거나, 오른쪽 x를 0으로 해석하여 표현식이 1로 평가되지만 여전히 IMHO는 좋지 않습니다.). 그러나 일단 'g x y = f y x'는 실제로 함수 ** 정의 **이고'f y x'는 ** body **라는 것을 알게되면 훨씬 더 합리적입니다. – Stephen

3

where은 완전히 새로운 기능을 선언 한 것과 완전히 동일하게 작동합니다. 유일한 차이점은 함수가 사용 된 지역 함수 범위에 함수가 있다는 것입니다. 즉, 호출 할 때 제공 한 코드는 다음과 같습니다.

flip' f -- Equivalent to flip' (\x y -> f x y) 
-- After we call it we have in our environment(scope) function f 

g x y = f y x -- Here you call it and it is perfectly fine, because f is defined 

유형은 어떻게됩니까? 컴파일러는 가지고있는 정보에 따라 g의 형식을 추론합니다. 정보는 g의 형식이 인수의 뒤집힌 순서를 제외하고는 f과 동일해야하며 f에는 두 개의 인수 만 있음을 알 수 있습니다. 따라서 유형 추론 알고리즘은 일반적으로 f :: a -> b -> c 인 경우 g :: b -> a -> c 인 경우라고 말합니다.

+1

그냥 기술적으로 "where"블록의 함수에 대해 유형을 명시 적으로 지정할 수 있습니다. ; 이러한 함수가 작고 명시적인 타입 선언만으로 혼란을 일으키기 때문에 (그리고 서명은 대개 외부 함수의 유형에서 명백합니다) 자주 수행되지 않습니다. – fjarri

+0

@Adrian이 유형 공제 및 범위에 대한 유용한 의견을 주셔서 감사합니다. 저는 여러분의 예제에 대해 조금 혼란 스럽습니다. 우리가'f '를 뒤집고''''''''''''''''의 몸체를 어떻게 정의 할 수 있습니까? (문제의 일부는'flip '(\ xy -> fxy)'와 같은 슬래시의 의미를 아직 드러내지 않은 것일 수도 있습니다.) ... 아직 내 공부에서 멀리까지 얻지 못했습니다. – Stephen

+0

@ Bogdan 감사합니다. 그 점은 함수 정의 일 뿐이라는 것을 더욱 분명하게 해줍니다. 그게 내가 처음으로 놓친 것입니다. – Stephen

2

두 번째 예제와 함께 특별한 아무것도 없다. 또한 첫 번째 예에서, 유형 서명은 선택 사항이므로, 다음 줄은 그 자체로 작동합니다

하스켈에서
flip'' f y x = f x y 

, 당신은 변수의 유형을 지정할 필요가 없습니다,하지만 하스켈 구현을 추론 할 수있다 너를 위해서. ghci에서 :t flip''을 사용하여 유추 유형 flip''이 예상 한 것임을 확인할 수 있습니다.

Haskell에서 선언없이 또는 형식없이 변수를 사용할 수 있습니까? 예를 들어 방정식의 = 기호 왼쪽에 있기 때문에 어딘가에 바인딩 된 변수 만 사용할 수 있습니다. 그리고 모든 변수는 a, bc과 같은 다형 유형 변수 인 경우에도 유형을 가져야합니다. 프로그래머가 타입을 Haskell 구현체로 선언 할 필요는 없지만 Haskell 구현체는 어떻게 변수가 사용되는지에 따라 타입을 결정할 수 있습니다.

이 "유형을 파악하는"비즈니스는 여전히 정적 입력입니다. 하스켈 구현은 먼저 모든 변수의 유형을 파악한 다음 프로그램을 컴파일하거나 실행합니다. 따라서 유형 오류가있는 경우 프로그램이 실행되기 전에 오류 메시지가 나타납니다.

+1

변수가 여전히 바인딩되어 있고 (심지어 다형 유형이라 할지라도) 유형을 가지고 있다는 것을 명시 해 주셔서 감사합니다. 그게 제가 확신 할 수 없었던 것입니다. 이는 정적 입력이기 때문에 동적 유형 지정을 의미하지는 않습니다. 즉, 다형성은 동적 입력을 의미하지 않습니다. – Stephen