OCaml의에서, .mli
에 가지고 법적 :η-확장
val f : 'a -> 'a
val g : 'a -> 'a
및 .ml
: F 번호에 그러나
let f x = x
let g = f
이 거부됩니다 :
eta_expand.ml(2,5): error FS0034: Module 'Eta_expand' contains
val g : ('a -> 'a)
but its signature specifies
val g : 'a -> 'a
The arities in the signature and implementation differ. The signature specifies that 'g' is function definition or lambda expression accepting at least 1 argument(s), but the implementation is a computed function value. To declare that a computed function value is a permitted implementation simply parenthesize its type in the signature, e.g.
val g: int -> (int -> int)
instead of
val g: int -> int -> int.
한 가지 해결 방법은 g의 정의를 η 확장하는 것입니다.
let g x = f x
내 코드가 실제로 (이 동일해야 (등 예외없이, 부작용,) 순수하게 기능적인 경우, 언어 유형을 일반화하는 방법에 따라, 다형성에 대한 더 나은 수 있습니다 : OCaml의에서 부분적인 애플리케이션은 다형 함수를 생성하지 않지만 η 확장은 그렇게한다.
체계적인 η 확장에 결점이 있습니까?
η 확장에 대한 두 가지 대답은 다음과 같습니다 .-) 대신 내 기능 유형 주변에 괄호를 추가하는 것이 좋습니다. 이는 분명히 F #이 입력 수준에서 함수의 "참"정의 (부분 응용에서와 같이 λ- 표현식과 계산 된 정의)를 구별하기 때문입니다. 아마도 λ- 표현식이 CLR 함수에 직접 매핑되고 계산 된 정의가 객체를 위임하기 때문에 매핑되는 것 같습니다. (나는이 해석 모르겠어요 및 F 번호에 대해 잘 알고 사람이 문서는이 기술 참조를 가리 수 있다면 감사하겠습니다.)
해결책 체계적으로 .mli
에 모든 기능 유형을 괄호를 추가하는 것입니다 만, 나는 이것이 비효율로 이어질 수 있다는 것을 두려워한다. 다른 하나는 계산 된 함수를 감지하고 해당 유형을 .mli
에 괄호로 묶는 것입니다. 세 번째 해법은 명백한 경우를 η 확장하고 다른 것은 괄호로 묶는 것이다.
중요한 성능이나 페널티를 유발하는 항목을 측정하기에 F #/CLR 내부에 익숙하지 않습니다.
그냥 val g : ('a ->'a)'로 지정하십시오. F # 유형 시스템의 알려진 기능/버그입니다. –
다시 말하면, "그냥 만드십시오"- 아마도 λ- 표현식과 계산 된 함수가 상호 교환 가능한 타입을 가지고 있지 않다면 그것은 좋은 이유입니다. 게다가 이것은 자동 생성 된 코드이기 때문에 문제는 단지 몇 개의 괄호를 수동으로 추가하는 것보다 조금 더 복잡합니다 ... –
이 경우 두 개의 차이점이 있습니다. 하나는 메소드로 컴파일되고 다른 하나는 정적' Func'속성. 호환성은 양방향 적이 지 않습니다 (즉,'a -> b : <: (a -> b)''(a -> b) : <: a -> b')가 아닙니다. –