Bu yüzden biraz daha düşündüm ve biraz ilerleme kaydettim. İşte Martin-Löf'ün hoş bir şekilde basit (ama tutarsız) Set : Set
sistemini birleştirici bir tarzda kodlamadaki ilk bıçak . Bitirmenin iyi bir yolu değil ama başlamak için en kolay yer burası. Bu tür teorisinin sözdizimi, tip ek açıklamaları, Pi türleri ve bir evren Kümesi içeren lambda hesabıdır.
Hedef Tipi Teorisi
Bütünlük aşkına, kuralları sunacağım. Bağlam geçerliliği, yalnızca, ' Set
lerde bulunan yeni değişkenleri birleştirerek boştan bağlamlar oluşturabileceğinizi söyler .
G |- valid G |- S : Set
. |- valid G, x:S |- valid
Ve şimdi, herhangi bir bağlamda terimler için türlerin nasıl sentezleneceğini ve bir şeyin türünü, içerdiği terimlerin hesaplama davranışına kadar nasıl değiştirebileceğimizi söyleyebiliriz.
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
Orijinalden küçük bir varyasyonda, lambda'yı tek bağlama operatörü yaptım, bu nedenle Pi'nin ikinci argümanı, dönüş türünün girdiye bağlı olma şeklini hesaplayan bir işlev olmalıdır. Geleneksel olarak (örneğin Agda'da, ama ne yazık ki Haskell'de değil), lambda'nın kapsamı olabildiğince sağa doğru genişler, bu nedenle genellikle daha yüksek düzey bir operatörün son argümanı olduklarında soyutlamaları köşesiz bırakabilirsiniz: Pi ile. Agda türünüz (x : S) -> T
olur Pi S \ x:S -> T
.
( ARASÖZ lambda üzerinde. Tip Açıklamalarda edebilmek istiyorsanız gerekli olan sentezlemek soyutlamaların türünü. Yazdığınız geçerseniz denetimini sizin çalışma yöntemi gibi, hala gibi bir beta-REDEX kontrol için ek açıklamaları ihtiyaç (\ x -> t) s
Eğer yolu yoktur olarak, Parçaların türlerini bütününkinden tahmin etmek. Modern tasarımcılara türleri kontrol etmelerini ve beta-redexleri söz diziminden hariç tutmalarını öneririm.)
( ARASÖZ . Bu sistem olarak tutarsızSet:Set
"yalancı paradoksları" çeşitli kodlama sağlar. Martin-Löf teorisini ortaya atarken, Girard kendi tutarsız Sistemi U. ona bunun bir kodlama gönderilen nedeniyle Hurkens sonraki paradoks bildiğimiz en temiz toksik yapı.)
Combinator Sözdizimi ve Normalleştirme
Her neyse, iki ekstra sembolümüz var, Pi ve Set, bu yüzden S, K ve iki ekstra sembolle birleşik bir çeviriyi yönetebiliriz: Evren için U ve ürün için P'yi seçtim.
Şimdi türlenmemiş kombinasyon sözdizimini (serbest değişkenlerle) tanımlayabiliriz:
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
Bu sözdizimine türle temsil edilen serbest değişkenleri dahil etme araçlarını dahil ettiğimi unutmayın . Benim açımdan bir refleks olmanın yanı sıra (isme layık olan her sözdizimi, return
değişkenleri gömme ve >>=
yerine geçme ikamesi içeren serbest bir monad'dir), terimleri birleştirici biçimlerine bağlama ile dönüştürme sürecinde ara aşamaları temsil etmek kullanışlı olacaktır.
İşte normalleştirme:
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 $.
(Okuyucu için bir alıştırma, tam olarak normal formlar için bir tür tanımlamak ve bu işlemlerin türlerini keskinleştirmektir.)
Tip Teorisini Temsil Etmek
Artık tür teorimiz için bir sözdizimi tanımlayabiliriz.
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 ve Hook tarzında bir de Bruijn indeks gösterimi kullanıyorum (Bird ve Paterson tarafından popüler hale getirildiği gibi). Tip Su a
birden fazla elemanına sahiptir a
, ve birlikte bir bağlayıcı altında serbest değişkenlerinin türü olarak kullanmak Ze
yeni bağlanmış değişken gibi Su x
eski serbest değişkenin kaydırılmış bir temsilidir x
.
Terimleri Birleştiricilere Çevirme
Ve bununla birlikte, parantez soyutlamasına dayalı olarak olağan çeviriyi elde ederiz .
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
Birleştiricileri Yazma
Çeviri, birleştiricileri kullanma şeklimizi gösteriyor, bu da bize türlerinin ne olması gerektiğine dair oldukça ipucu veriyor. U
ve P
sadece set yapıcılarıdır, bu nedenle, çevrilmemiş türler yazmak ve Pi için "Agda gösterimine" izin vermek,
U : Set
P : (A : Set) -> (B : (a : A) -> Set) -> Set
Birleştirici K
, bir türden bir değeri A
başka bir türden sabit bir işleve kaldırmak için kullanılır G
.
G : Set A : Set
K : (a : A) -> (g : G) -> A
Birleştirici S
, uygulamaları tüm parçaların bağlı olabileceği bir tip üzerinde kaldırmak için kullanılır.
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)
Türüne bakarsanız , tür teorisinin bağlamsal uygulama kuralını S
tam olarak belirttiğini görürsünüz, bu yüzden uygulama yapısını yansıtmayı uygun kılan da budur. Bu onun işi!
O zaman sadece kapalı şeyler için başvurumuz var
f : Pi A B
a : A
f a : B a
Ama bir engel var. Birleştirici türlerini, birleşim tipi kuramında değil, sıradan tür kuramında yazdım. Neyse ki çeviriyi yapacak bir makinem var.
Kombine Tip Sistem
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
İşte karşınızda, tüm okunamayan ihtişamıyla: birleşik bir sunumu Set:Set
!
Hala biraz sorun var. Sistemin sözdizimi , sadece terimlerden G
, A
ve B
için S
ve benzer şekilde parametrelerini tahmin etmenize olanak vermez K
. Buna karşılık olarak, türetmeleri algoritmik olarak yazmayı doğrulayabiliriz , ancak orijinal sistemde yapabildiğimiz gibi sadece birleştirici terimleri yazamayız. İşe yarayabilecek şey, typechecker girdisinin türetmeyi etkin bir şekilde kaydederek S ve K kullanımlarına ilişkin tip açıklamaları taşımasını gerektirmektir. Ama bu başka bir solucan kutusu ...
Başlamak için yeterince hevesliysen, burası durmak için iyi bir yer. Gerisi "perde arkası" meselesi.
Birleştirici Türlerinin Oluşturulması
İlgili tip teori terimlerinden köşeli parantez soyutlama çevirisini kullanarak bu birleştirici türleri oluşturdum. Bunu nasıl yaptığımı göstermek ve bu yazıyı tamamen anlamsız hale getirmek için ekipmanımı sunayım.
Kombinatör tiplerini tamamen parametreleri üzerinden aşağıdaki gibi yazabilirim. Benim kullanışlı faydalanmak pil
alanı türünü tekrarlamaktan kaçınmak için Pi ve lambda birleştirir ve oldukça yardımsever bana bağlamak değişkenlere Haskell'ın fonksiyon alanını kullanmasına izin verir fonksiyonu. Belki de neredeyse aşağıdakileri okuyabilirsiniz!
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)
Bunları tanımlayarak, ilgili açık alt terimleri çıkardım ve çeviriden geçirdim.
A de Bruijn Kodlama Araç Seti
İşte nasıl inşa edileceği pil
. İlk olarak, Fin
değişkenler için kullanılan bir ite kümeleri sınıfı tanımlıyorum . Bu türden her kümede, emb
yukarıdaki kümede kurucu-koruyan bir düzenleme, artı yeni bir top
öğe bulunur ve bunları birbirinden ayırabilirsiniz: embd
işlev, görüntüsünde bir değer olup olmadığını söyler emb
.
class Fin x where
top :: Su x
emb :: x -> Su x
embd :: Su x -> Maybe x
Biz can, tabii ki, örneğini Fin
için Ze
veSuc
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)
Şimdi zayıflama işlemiyle daha az veya eşit olarak tanımlayabilirim .
class (Fin x, Fin y) => Le x y where
wk :: x -> y
wk
Fonksiyon unsurlarını gömmek gerekir x
olarak büyük unsurları y
ilave işler böylece, y
küçük ve dolayısıyla daha yerel olarak bağlanmış, Bruijn indeks açısından de içinde.
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)
Ve bunu çözdüğünüzde, gerisini biraz n kafa kafatasları halleder.
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)
Üst düzey fonksiyon size sadece değişkeni temsil eden bir terim vermekle kalmaz, aynı zamanda değişkenin görünür olduğu herhangi bir kapsamda değişkenin doğru temsili haline gelen aşırı yüklenmiş bir şey verir . Yani, farklı kapsamları türe göre ayırt etme zahmetine girmiş olmam, Haskell tip denetleyicisine çeviri için gerekli olan de Bruijn gösterimine geçişi hesaplamak için yeterli bilgi verir. Neden bir köpek tutup kendine havlayasın?