이 참조에서 : 엄격한 양성
엄격한 양성 조건은 다음과 같은 선언을 배제합니다.
data Bad : Set where
bad : (Bad → Bad) → Bad
A B C
-- A is in a negative position, B and C are OK
A가 왜 음수입니까? 또한 왜 B가 허용됩니까? C가 허용되는 이유를 이해합니다.
답변
ㅏ⇒비
ㅏ
비
이제 유도 데이터 유형에 대해
티
티
티
대수에서는 연산이 유한 한 수의 인수를 취하는 것이 일반적이며 대부분의 경우 0 (일정), 1 (단항) 또는 2 (이진) 인수가 필요합니다. 데이터 유형의 생성자에 대해 이것을 일반화하는 것이 편리합니다. c
데이터 유형의 생성자가 있다고 가정합니다 T
.
- 경우
c
상수 우리는 함수로 생각할 수 있습니다unit -> T
동등하거나(empty -> T) -> T
, - 경우
c
단항 우리가 함수로 생각할 수있는T -> T
, 또는 동등하게(unit -> T) -> T
, - 경우
c
우리가 함수로 생각할 수 이진T -> T -> T
, 또는 동등T * T -> T
또는 동등(bool -> T) -> T
, - 우리는 생성자 원한다면
c
일곱 인수를, 우리는 함수로 볼 수있는 일곱 개 요소와 일부 이전에 정의 된 유형입니다.(seven -> T) -> T
seven
- 또한
c
무수히 많은 인수를 취하는 생성자 를 가질 수 있습니다(nat -> T) -> T
.
이 예제는 일반적인 형태의 생성자가
c : (A -> T) -> T
여기서 우리 A
는 arity 를 호출 하고 의 요소를 생성하기 위해 type의 많은 인수 를 취하는 생성자로 c
생각 합니다.c
A
T
T
arities 정의해야합니다 여기에 매우 중요한 일입니다 전에 우리는 정의 T
, 그렇지 않으면 우리는 생성자가 일을 할 생각 무엇을 말할 수는. 누군가 생성자를 가지려고하면
broken: (T -> T) -> T
그렇다면 “얼마나 많은 논쟁이 필요 broken
합니까?” 좋은 대답이 없습니다. ” T
다수의 인수를 받는다 “는 대답을 시도 할 수도 있지만 T
아직 정의되지 않았기 때문에 그렇지 않습니다. 우리는 멋진 고정 소수점 이론을 사용하여 유형 T
과 주입 함수 를 찾아서 입체에서 벗어나려고 노력할 수도 (T -> T) -> T
있지만 성공할 수도 있지만 유도 원칙을 깨뜨릴 수도 있습니다 T
. 따라서 그러한 것을 시도하는 것은 나쁜 생각입니다.
λ
V
λ⋅V
c
B
c : B * (A -> T) -> T
실제로, 많은 생성자는이 방법으로 다시 작성할 수 있습니다, 전부는 아니지만, 우리는 즉 우리가 허용해야, 한 단계를 필요로 A
하는 의존 에 B
:
c : (∑ (x : B), A x -> T) -> T
이것은 유도 형 생성자의 최종 형태입니다. 또한 W- 타입이 바로 그것입니다. 형식은 매우 일반적이므로 단일 생성자 만 있으면됩니다 c
! 실제로 두 가지가 있다면
d' : (∑ (x : B'), A' x -> T) -> T
d'' : (∑ (x : B''), A'' x -> T) -> T
우리는 그것들을 하나로 결합 할 수 있습니다
d : (∑ (x : B), A x -> T) -> T
어디
B := B' + B''
A(inl x) := A' x
A(inr x) := A'' x
그건 그렇고, 우리가 일반적인 형태를 카레하면 우리는 그것이
c : ∏ (x : B), ((A x -> T) -> T)
사람들이 실제로 증거 조수에 적는 것에 더 가깝습니다. 증거 어시스턴트를 사용하면 생성자를 편리한 방식으로 작성할 수 있지만 위의 일반적인 형식 (운동)과 동일합니다.
답변
첫 번째 항목은 Bad
함수 인수를 나타 내기 때문에 ‘음수’라고합니다. 즉, 함수 화살표의 왼쪽에 있습니다 ( Philip Wadler가 무료 로 재귀 유형 참조 ). ‘부정적 위치’라는 용어의 원점은 역 분산 의 개념에서 비롯된 것 같습니다 ( ‘콘트라’는 반대를 의미합니다).
유형을 사용하여 종료되지 않는 프로그램을 작성할 수 있기 때문에 유형이 음의 위치에 정의되어서는 안됩니다. 즉, 강력한 정규화가 존재하지 않습니다 (아래에 자세히 설명되어 있음). 그건 그렇고, 이것이 ‘엄격 양성’이라는 규칙의 이름에 대한 이유입니다. 우리는 부정적인 입장을 허용하지 않습니다.
우리는 Bad
종료가 발생 하지 않기 때문에 두 번째 발생을 허용하고 재귀 데이터 유형의 Bad
어느 시점에서 ( 생성자의 마지막 화살표 앞에 ) 정의되는 유형 ( )을 사용하려고합니다 .
다음 정의가 엄격한 양성 규칙을 위반 하지 않는다는 것을 이해하는 것이 중요합니다 .
data Good : Set where
good : Good → Good → Good
이 규칙은 생성자 인수 ( Good
이 경우 모두)에만 적용되며 생성자 자체에는 적용되지 않습니다 (Adam Chlipala의 ” 종속적 유형을 사용한 인증 된 프로그래밍 “참조).
엄격한 양성을 위반하는 또 다른 예 :
data Strange : Set where
strange : ((Bool → Strange) → (ℕ → Strange)) → Strange
^^ ^
this Strange is ...this arrow
to the left of...
부정적인 위치에 대한 이 답변 을 확인할 수도 있습니다 .
비 종료에 대한 추가 정보 … 참조한 페이지에 설명이 포함되어 있습니다 (Haskell의 예와 함께).
엄격하지 않은 선언은이를 사용하여 종료되지 않는 함수를 작성할 수 있으므로 거부됩니다. 위에서 잘못된 데이터 유형을 사용하여 루핑 정의를 작성하는 방법을 보려면 BadInHaskell을 참조하십시오 .
다음은 Ocaml의 유사한 예제로, 재귀를 직접 사용하여 (!)없이 재귀 동작을 구현하는 방법을 보여줍니다 .
type boxed_fun =
| Box of (boxed_fun -> boxed_fun)
(* (!) in Ocaml the 'let' construct does not permit recursion;
one have to use the 'let rec' construct to bring
the name of the function under definition into scope
*)
let nonTerminating (bf:boxed_fun) : boxed_fun =
match bf with
Box f -> f bf
let loop = nonTerminating (Box nonTerminating)
이 nonTerminating
함수는 인수에서 함수를 “풀고”원래 인수에이를 적용합니다. 여기서 중요한 것은 대부분의 유형 시스템이 함수를 자신에게 전달하는 것을 허용하지 않으므로 f f
유형 f
검사기를 충족시킬 유형이 없기 때문에 유형 검사 와 같은 용어 는 유형 검사를하지 않습니다 . 유형 시스템이 도입 된 이유 중 하나는 자체 응용 프로그램을 비활성화하는 것입니다 ( 여기 참조 ).
위에서 소개 한 것과 같은 랩핑 데이터 유형을 사용하여 불일치로가는 길에서이로드 블록을 우회 할 수 있습니다.
비 종료 계산이 논리 시스템에 불일치를 초래한다고 덧붙이고 싶습니다. Agda 및 Coq의 경우 False
유도 데이터 유형에 생성자가 없으므로 False 유형의 증명 용어를 작성할 수 없습니다. 그러나 경우 비 종료 계산이 허용 된 하나의 예를 들어 이런 식으로 (COQ)에 그것을 할 수 있습니다 :
Fixpoint loop (n : nat) : False = loop n
그런 다음 loop 0
typecheck giving loop 0 : False
을 입력하므로 Curry-Howard 서신에서 이는 잘못된 제안을 증명했음을 의미합니다.
Upshot : 귀납적 정의에 대한 엄격한 양성 규칙은 논리에 비참한 비 종료 계산을 방지합니다.