2014-04-20 2 views
2

나는이 OCaml walking through 슬라이드를 읽고있다, 나는 여기 intersting 질문 찾습니다"currying"요구 사항이 중요한 이유는 무엇입니까?

the type of this expression contains type variables that cannot be generalized 

난 몰라 :

enter image description here

그 함수가 컴파일 오류가 발생합니다 아차 것을 이유는 내 Mac에서 OCaml 버전 4.01.0을 사용하여이 기능에 대한 몇 가지 테스트를 빨리 마친 것입니다. 이 코드를 해석 할 때 오류가 표시되지 않았습니다.

나는 왜 슬라이드가 카레 때문에 오류라고 주장하는지 모르겠다. 나는이 오류를 다시 만들 수 없다 ...

누구도 나에게 도움을 줄 수 있을까?

답변

9

컴파일러는이 오류에 대해 불평하지만 최상위는 않습니다.

$ cat ungen.ml 
open List 
let oops = fold_left (fun a _ -> a + 1) 0 
$ ocamlc -c ungen.ml 
File "ungen.ml", line 2, characters 11-41: 
Error: The type of this expression, '_a list -> int, 
     contains type variables that cannot be generalized 

문제는 여전히 최상위 레벨에 있습니다. 당신이 목록 (안 제로 또는 2 개)의 단 하나의 유형 oops를 사용하는 경우에는이 있음을

$ ocaml 
     OCaml version 4.01.0 

# open List;; 
# let oops = fold_left (fun a _ -> a + 1) 0;; 
val oops : '_a list -> int = <fun> 
# oops [1;2;3;4];; 
- : int = 4 
# oops ['a';'b';'c'];; 
Error: This expression has type char but an expression was expected of type 
     int 
# 

참고 : 다른 종류의 두 개의리스트의 길이를 계산하는 oops를 사용하지하려고하면 당신은 그것을 볼 것이다 오류. 컴파일러는 oops (내 보낸 심볼)을 0 번 사용하면 전체 모듈을 볼 수 있고 oops이 어떻게 사용되는지 알 수 있으므로 불평 할 수 있습니다. toplevel은 사용자가 다음에 입력 할 내용을 모르기 때문에 zero 용도에 대해 불평 할 수 없습니다.

죄송 업데이트, 나는 실제 오류가 무엇인지에 대한 자세한 내용을 말했다한다 (수준에서 나는 그것을 이해). 내 의견으로는 이것은 currying과 거의 관련이 없다.

이것은 유명한 "가치 제한"입니다. 값 제한에 대한 간단한 설명은 다음과 같습니다. 일반화 할 수없는 일부 표현식이 있습니다. 즉, 다형성으로 만들 수 없으므로 모든 유형과 함께 사용할 수 있습니다. 간단한 예를 들어이 같은 것입니다 : 당신이 유형 'a list ref을 가지고 mylist을 허용하는 경우

let mylist = ref [] 

, 당신은 안전하지 않습니다 그것의 모든 다른 유형의 목록을 저장할 수 있습니다.

그러나,이 일반화하는 것이 안전하다 : 유형 'a listmylist2을 일반화에 문제가 없습니다

let mylist2 = [] 

.

OCaml과 같은 현대의 ML 파생물에서 일반화에 대한 제한이 다소 단순한 규칙으로 축소되었습니다. "값"(예 : [])을 일반화 할 수 있습니다. 값이 아닌 표현식 (예 : ref [])은 일반화 할 수 없습니다.

식 :

fold_left (fun a _ -> a + 1) 0 

값은 아니다. ref []과 같은 거친 형태의 함수 응용 프로그램입니다. 이것은 (분명히) oops의 정의입니다. 한편

, 식 :

fun xs -> fold_left (fun a _ -> a + 1) 0 xs 

값이다; 그것은 람다입니다. 그래서 일반화 될 수 있습니다. 이것은 (편리한 구문 약어를 펼친 후에) 위의 len의 정의입니다. 그래서 len은 모든 목록에서 작동하지만 oops은 그리 유용하지 않습니다.

값과 값이 아닌 값의 구별은 구문 론적입니다. 즉, 단지 표현의 형태를 국부적으로 바라 봄으로써 결정될 수있다. 결정을 내리는 데있어 표현의 유형이나 의미에 대해 알 필요가 없습니다.

현재 양식에서 값 제한을 사용하는 한 가지 인수는 대부분 oops 형식 대신 len 형태로 정의하여 함수의 원하는 일반화 (즉, 다형성)를 복구 할 수 있다는 것입니다. . 이 간단한 변환을 "η 확장"이라고합니다.

η 확장은 구문 만 변경하지만 함수의 의미는 변경하지 않는다는 사실은 값 제한이 근사치임을 보여줍니다. 즉, 일반화하기에 안전 할 수있는 몇 가지 표현을 일반화하는 것을 금지합니다. 그러나 실제 프로그램에서 발생하는 경우에는 너무 간단하지 않고 제한적이지 않습니다.

OCaml 3.07 이후 OCaml의 값 제한이 기본 ML보다 향상되어 많은 경우에 일반화가 가능해졌습니다. 여기에서 읽을 수 있습니다 : J. Garrigue, Relaxing the Value Restriction. 이 논문은 또한 가치 제한과 그 역사에 대한 탁월한 캡슐 요약을 포함하고 있습니다.

+0

안녕하세요. Jeffrey, 답변 해 주셔서 감사합니다. 하지만 기본적으로 컴파일러가 허용하지 않는 이유는 무엇입니까? 이 슬라이드의 머리에서, 그것은 "currying"과 관련된 것이기 때문에 ..? 나는 "currying"의 기본 개념을 알고 있지만, "currying"이이 맥락에서 중요한 이유는 모르겠습니다. – computereasy

+0

이것은 정말 훌륭한 답변입니다! 정말 고마워 ! – computereasy

관련 문제