그래서 조금 더 생각하고 진전을 이루었습니다. Martin-Löf의 유쾌하고 단순한 (그러나 일관성이없는) Set : Set
시스템을 조합 스타일 로 인코딩하는 첫 번째 찌르기 입니다. 끝내기에 좋은 방법은 아니지만 시작하기 가장 쉬운 곳입니다. 이 유형 이론의 구문은 유형 주석, Pi 유형 및 유니버스 세트가있는 람다 미적분입니다.
목표 유형 이론
완전성을 위해 규칙을 제시하겠습니다. 컨텍스트 유효성은 Set
s에 서식하는 새로운 변수를 인접하여 비어있는 상태에서 컨텍스트를 구축 할 수 있다고 말합니다 .
G |- valid G |- S : Set
. |- valid G, x:S |- valid
이제 우리는 주어진 문맥에서 용어에 대한 유형을 합성하는 방법과 포함 된 용어의 계산 동작까지 어떤 유형을 변경하는 방법을 말할 수 있습니다.
G |- valid G |- S : Set G |- T : Pi S \ x:S -> Set
G |- Set : Set G |- Pi S T : Set
G |- S : Set G, x:S |- t : T x G |- f : Pi S T G |- s : S
G |- \ x:S -> t : Pi S T G |- f s : T s
G |- valid G |- s : S G |- T : Set
G |- x : S G |- s : T
원본에서 약간의 변형으로 람다를 유일한 바인딩 연산자로 만들었으므로 Pi의 두 번째 인수는 반환 유형이 입력에 의존하는 방식을 계산하는 함수 여야합니다. 관례에 따라 (예를 들어 Agda에서는하지만 슬프게도 Haskell에서는 아님) 람다의 범위가 가능한 한 오른쪽으로 확장되므로, 고차 연산자의 마지막 인수 일 때 추상화를 괄호로 묶지 않은 채로 둘 수 있습니다. Pi와 함께. 귀하의 Agda 유형 (x : S) -> T
은 Pi S \ x:S -> T
.
( Digression . 추상화 유형 을 합성 할 수 있으려면 람다에 대한 유형 주석이 필요합니다 . 모드 작업 으로 유형 검사 로 전환하는 경우 에도 (\ x -> t) s
방법이 없으므로 베타 redex와 같은 유형을 검사 하려면 주석이 필요합니다. 전체에서 부품의 유형을 추측하기 위해 현대 디자이너에게 유형을 확인하고 바로 구문에서 베타 redexes를 제외하도록 조언합니다.)
( Digression .이 시스템은 Set:Set
다양한 "거짓말 역설"의 인코딩을 허용하기 때문에 일관성이 없습니다 . Martin-Löf가이 이론을 제안했을 때 Girard는 그에게 일관성없는 시스템 U로 인코딩을 보냈습니다. Hurkens로 인한 후속 역설은 다음과 같습니다. 우리가 알고있는 가장 유독 한 구조.)
조합기 구문 및 정규화
어쨌든 두 개의 추가 기호, Pi 및 Set이 있으므로 S, K 및 두 개의 추가 기호를 사용하여 조합 번역을 관리 할 수 있습니다. 저는 우주를 위해 U를 선택하고 제품을 위해 P를 선택했습니다.
이제 유형이 지정되지 않은 조합 구문 (자유 변수 포함)을 정의 할 수 있습니다.
data SKUP = S | K | U | P deriving (Show, Eq)
data Unty a
= C SKUP
| Unty a :. Unty a
| V a
deriving (Functor, Eq)
infixl 4 :.
a
이 구문 에 유형 으로 표현되는 자유 변수를 포함하는 방법을 포함했습니다 . 내 입장에서 반사되는 것 외에도 (이름에 걸 맞는 모든 구문은 return
변수 를 포함하고 >>=
대체를 수행 하는 무료 모나드 임) 조합 형식에 바인딩하여 용어를 변환하는 과정에서 중간 단계를 나타내는 것이 편리 할 것입니다.
정규화는 다음과 같습니다.
norm :: Unty a -> Unty a
norm (f :. a) = norm f $. a
norm c = c
($.) :: Unty a -> Unty a -> Unty a
C S :. f :. a $. g = f $. g $. (a :. g)
C K :. a $. g = a
n $. g = n :. norm g
infixl 4 $.
(독자를위한 연습은 정확히 정상적인 형태에 대한 유형을 정의하고 이러한 작업의 유형을 선명하게하는 것입니다.)
유형 이론 표현
이제 유형 이론에 대한 구문을 정의 할 수 있습니다.
data Tm a
= Var a
| Lam (Tm a) (Tm (Su a))
| Tm a :$ Tm a
| Pi (Tm a) (Tm a)
| Set
deriving (Show, Functor)
infixl 4 :$
data Ze
magic :: Ze -> a
magic x = x `seq` error "Tragic!"
data Su a = Ze | Su a deriving (Show, Functor, Eq)
나는 Bellegarde and Hook 방식으로 de Bruijn 인덱스 표현을 사용합니다 (Bird와 Paterson에 의해 대중화 됨). 유형 Su a
에는보다 하나 이상의 요소가 있으며, 새로 바인딩 된 변수로 이전 자유 변수의 이동 된 표현 인 a
바인더 아래의 자유 변수 유형으로 사용합니다 .Ze
Su x
x
용어를 결합 자로 번역
이 작업이 완료되면 대괄호 추상화를 기반으로 일반적인 번역을 얻습니다 .
tm :: Tm a -> Unty a
tm (Var a) = V a
tm (Lam _ b) = bra (tm b)
tm (f :$ a) = tm f :. tm a
tm (Pi a b) = C P :. tm a :. tm b
tm Set = C U
bra :: Unty (Su a) -> Unty a
bra (V Ze) = C S :. C K :. C K
bra (V (Su x)) = C K :. V x
bra (C c) = C K :. C c
bra (f :. a) = C S :. bra f :. bra a
조합기 입력
번역은 우리가 결합자를 사용하는 방법을 보여 주므로 그 유형이 무엇인지에 대한 단서를 제공합니다. U
그리고 P
단지 설정된 생성자이므로 번역되지 않은 유형을 작성하고 Pi에 대해 "Agda 표기법"을 허용하면
U : Set
P : (A : Set) -> (B : (a : A) -> Set) -> Set
K
연결자 일부 유형의 값을 올리 데 사용되는 A
일부 다른 타입에 대해 일정한 기능 G
.
G : Set A : Set
K : (a : A) -> (g : G) -> A
S
콤비는 모든 부품이 의존 할 수있는시 유형을 통해 리프트 응용 프로그램에 사용됩니다.
G : Set
A : (g : G) -> Set
B : (g : G) -> (a : A g) -> Set
S : (f : (g : G) -> (a : A g) -> B g a ) ->
(a : (g : G) -> A g ) ->
(g : G) -> B g (a g)
유형을 살펴보면 유형 이론 S
의 상황에 맞는 응용 규칙을 정확하게 설명하는 것을 알 수 있으므로 응용 프로그램 구성을 반영하는 데 적합합니다. 그게 직업입니다!
그런 다음 폐쇄 된 항목에만 적용됩니다.
f : Pi A B
a : A
f a : B a
하지만 걸림돌이 있습니다. 나는 결합 유형 이론이 아닌 일반 유형 이론에서 결합 자의 유형을 작성했습니다. 다행히 번역을 할 기계가 있습니다.
조합형 시스템
U : U
P : PU(S(S(KP)(S(S(KP)(SKK))(S(KK)(KU))))(S(KK)(KU)))
G : U
A : U
K : P[A](S(S(KP)(K[G]))(S(KK)(K[A])))
G : U
A : P[G](KU)
B : P[G](S(S(KP)(S(K[A])(SKK)))(S(KK)(KU)))
S : P(P[G](S(S(KP)(S(K[A])(SKK)))(S(S(KS)(S(S(KS)(S(KK)(K[B])))(S(KK)(SKK))))
(S(S(KS)(KK))(KK)))))(S(S(KP)(S(S(KP)(K[G]))(S(S(KS)(S(KK)(K[A])))
(S(S(KS)(KK))(KK)))))(S(S(KS)(S(S(KS)(S(KK)(KP)))(S(KK)(K[G]))))
(S(S(KS)(S(S(KS)(S(KK)(KS)))(S(S(KS)(S(S(KS)(S(KK)(KS)))
(S(S(KS)(S(KK)(KK)))(S(KK)(K[B])))))(S(S(KS)(S(S(KS)(S(KK)(KS)))(S(KK)(KK))))
(S(KK)(KK))))))(S(S(KS)(S(S(KS)(S(KK)(KS)))(S(S(KS)(S(KK)(KK)))
(S(S(KS)(KK))(KK)))))(S(S(KS)(S(S(KS)(S(KK)(KS)))(S(KK)(KK))))(S(KK)(KK)))))))
M : A B : U
M : B
그래서 여러분은 읽을 수없는 모든 영광 속에 그것을 가지고 있습니다 : Set:Set
!
여전히 약간의 문제가 있습니다. 시스템의 구문은 당신에게 추측 할 수있는 방법을 제공하지 않습니다 G
, A
그리고 B
매개 변수 S
와 유사위한 K
단지 용어에서. 이에 따라 우리는 알고리즘 적으로 타이핑 파생을 검증 할 수 있지만 원래 시스템에서 할 수있는 것처럼 결합 자 용어를 타입 체크 할 수는 없습니다. 작동 할 수있는 것은 S 및 K 사용에 대한 유형 주석을 포함하도록 유형 검사기에 입력을 요구하여 효과적으로 파생을 기록하는 것입니다. 하지만 그것은 또 다른 웜 캔입니다 ...
시작하기에 충분히 열성적 이었다면이 곳은 멈출 수있는 좋은 장소입니다. 나머지는 "비하인드 스토리"입니다.
결합기 유형 생성
나는 관련 유형 이론 용어에서 대괄호 추상화 번역을 사용하여 이러한 조합 유형을 생성했습니다. 내가 어떻게했는지 보여주고이 게시물이 무의미하지 않게 만들기 위해 내 장비를 제공하겠습니다.
다음과 같이 매개 변수에 대해 완전히 추상화 된 결합기 유형을 작성할 수 있습니다. 필자 pil
는 Pi와 lambda를 결합하여 도메인 유형을 반복하지 않는 편리한 함수를 사용하고, Haskell의 함수 공간을 사용하여 변수를 바인딩 할 수 있습니다. 아마도 다음을 거의 읽을 수있을 것입니다!
pTy :: Tm a
pTy = fmap magic $
pil Set $ \ _A -> pil (pil _A $ \ _ -> Set) $ \ _B -> Set
kTy :: Tm a
kTy = fmap magic $
pil Set $ \ _G -> pil Set $ \ _A -> pil _A $ \ a -> pil _G $ \ g -> _A
sTy :: Tm a
sTy = fmap magic $
pil Set $ \ _G ->
pil (pil _G $ \ g -> Set) $ \ _A ->
pil (pil _G $ \ g -> pil (_A :$ g) $ \ _ -> Set) $ \ _B ->
pil (pil _G $ \ g -> pil (_A :$ g) $ \ a -> _B :$ g :$ a) $ \ f ->
pil (pil _G $ \ g -> _A :$ g) $ \ a ->
pil _G $ \ g -> _B :$ g :$ (a :$ g)
이러한 정의를 통해 관련 공개 하위 용어를 추출 하여 번역을 실행했습니다.
Bruijn 인코딩 툴킷
빌드하는 방법은 다음과 같습니다 pil
. 첫째, Fin
변수에 사용되는 ite 세트 의 클래스를 정의 합니다. 이러한 모든 집합에는 위 집합에 대한 생성자 보존 emb
테두리와 새 top
요소가 있으며이를 구분할 수 있습니다. embd
함수는 값이의 이미지에 있는지 여부를 알려줍니다 emb
.
class Fin x where
top :: Su x
emb :: x -> Su x
embd :: Su x -> Maybe x
우리가 할 수있는, 물론, 인스턴스화 Fin
에 대한 Ze
과Suc
instance Fin Ze where
top = Ze
emb = magic
embd _ = Nothing
instance Fin x => Fin (Su x) where
top = Su top
emb Ze = Ze
emb (Su x) = Su (emb x)
embd Ze = Just Ze
embd (Su x) = fmap Su (embd x)
이제 약화 작업으로 작 거나 같음을 정의 할 수 있습니다 .
class (Fin x, Fin y) => Le x y where
wk :: x -> y
wk
기능 요소 삽입한다 x
은 AS 최대 의 요소 y
에 추가 것들이되도록, y
작은, 따라서 더 로컬 바인딩 브루 인덱스 조건 데있다.
instance Fin y => Le Ze y where
wk = magic
instance Le x y => Le (Su x) (Su y) where
wk x = case embd x of
Nothing -> top
Just y -> emb (wk y)
그리고 일단 분류를 마치면, 나머지는 랭크 n skullduggery가 처리합니다.
lam :: forall x. Tm x -> ((forall y. Le (Su x) y => Tm y) -> Tm (Su x)) -> Tm x
lam s f = Lam s (f (Var (wk (Ze :: Su x))))
pil :: forall x. Tm x -> ((forall y . Le (Su x) y => Tm y) -> Tm (Su x)) -> Tm x
pil s f = Pi s (lam s f)
고차 함수는 변수를 나타내는 용어를 제공 할뿐만 아니라 변수가 표시되는 모든 범위에서 변수의 올바른 표현이 되는 오버로드 된 것을 제공합니다 . 즉, 유형별로 다른 스코프를 구별하는 문제가 발생한다는 사실 은 하스켈 유형 검사기가 de Bruijn 표현으로의 변환에 필요한 이동을 계산하기에 충분한 정보를 제공합니다. 개를 키우고 짖는 이유는 무엇입니까?