Sezgisel tip teorisinin birleşimsel mantık eşdeğeri nedir?


87

Yakın zamanda Haskell ve Agda'yı (bağımlı tipte bir işlevsel programlama dili) içeren bir üniversite kursunu tamamladım ve bunlarda lambda hesabını birleştirici mantıkla değiştirmenin mümkün olup olmadığını merak ediyordum. Haskell ile bu, S ve K kombinasyonlarını kullanarak mümkün görünüyor, bu da onu noktasız hale getiriyor. Agda için eşdeğerinin ne olduğunu merak ediyordum. Yani, herhangi bir değişken kullanmadan, bağımlı olarak yazılmış bir işlevsel programlama dili Agda'ya eşdeğer yapılabilir mi?

Ayrıca, nicelemeyi bir şekilde birleştiricilerle değiştirmek mümkün müdür? Bunun bir tesadüf olup olmadığını bilmiyorum ama evrensel niceleme, örneğin bir tür imzasının lambda ifadesi gibi görünmesini sağlar. Anlamını değiştirmeden bir tür imzasından evrensel nicelleştirmeyi kaldırmanın bir yolu var mı? Örn:

forall a : Int -> a < 0 -> a + a < a

Aynı şey bir forall kullanmadan da ifade edilebilir mi?


21
K (kolay) ve S (oldukça kıllı) için mümkün olan en bağımlı türleri bulmaya başlayın. Set ve Pi için sabitler atıp ardından temel (tutarsız) Set: Set sistemini yeniden yapılandırmak ilginç olurdu. Daha fazla düşünürdüm ama yakalamam gereken bir uçak var.
pigworker

Yanıtlar:


52

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 : Setsistemini 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, ' Setlerde bulunan yeni değişkenleri birleştirerek boştan bağlamlar oluşturabileceğinizi söyler .

                     G |- valid   G |- S : Set
--------------     ----------------------------- x fresh for G
  . |- 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
-------------- x:S in G     ----------------------------- S ={beta} T
  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) -> Tolur 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) sEğ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 :.

aBu 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, returndeğ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        -- requires first arg in normal form
C S :. f :. a $. g  = f $. g $. (a :. g)  -- S f a g = f g (a g)   share environment
C K :. a $. g       = a                   -- K a g = a             drop environment
n $. g              = n :. norm g         -- guarantees output in normal form
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))    -- Lam is the only place where binding happens
  | Tm a :$ Tm a
  | Pi (Tm a) (Tm a)          -- the second arg of Pi is a function computing a Set
  | 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 abirden fazla elemanına sahiptir a, ve birlikte bir bağlayıcı altında serbest değişkenlerinin türü olarak kullanmak Zeyeni bağlanmış değişken gibi Su xeski 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               -- binds a variable, building a function
bra (V Ze)      = C S :. C K :. C K        -- the variable itself yields the identity
bra (V (Su x))  = C K :. V x               -- free variables become constants
bra (C c)       = C K :. C c               -- combinators become constant
bra (f :. a)    = C S :. bra f :. bra a    -- S is exactly lifted application

Birleştiricileri Yazma

Çeviri, birleştiricileri kullanma şeklimizi gösteriyor, bu da bize türlerinin ne olması gerektiğine dair oldukça ipucu veriyor. Uve Psadece 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 Abaş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ı Stam 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
----------------- A ={norm} B
  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, Ave Biçin Sve 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 pilalanı 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, Findeğişkenler için kullanılan bir ite kümeleri sınıfı tanımlıyorum . Bu türden her kümede, embyukarıdaki kümede kurucu-koruyan bir düzenleme, artı yeni bir topöğe bulunur ve bunları birbirinden ayırabilirsiniz: embdiş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 Finiçin ZeveSuc

instance Fin Ze where
  top = Ze              -- Ze is the only, so the highest
  emb = magic
  embd _ = Nothing      -- there was nothing to embed

instance Fin x => Fin (Su x) where
  top = Su top          -- the highest is one higher
  emb Ze     = Ze            -- emb preserves Ze
  emb (Su x) = Su (emb x)    -- and Su
  embd Ze      = Just Ze           -- Ze is definitely embedded
  embd (Su x)  = fmap Su (embd x)  -- otherwise, wait and see

Ş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

wkFonksiyon unsurlarını gömmek gerekir xolarak büyük unsurları yilave işler böylece, yküçü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    -- nothing to embed

instance Le x y => Le (Su x) (Su y) where
  wk x = case embd x of
    Nothing  -> top          -- top maps to top
    Just y   -> emb (wk y)   -- embedded gets weakened and embedded

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?


bu çok saçma olabilir ama Fbirleştiriciyi eklerseniz bu resim nasıl değişir ? Fİlk argümanına bağlı olarak farklı davranır: If Abir atomsa Mve Nterimlerse ve PQbir bileşikse, o zaman FAMN -> Mve F(PQ)MN -> NPQ. Bu, SK(I)analizde gösterilemez, ancak Kolarak temsil edilebilir FF. Bununla puansız MLTT'nizi genişletmek mümkün mü?
kram1032

Bu parantez soyutlama prosedüründe bir sorun olduğundan oldukça eminim, özellikle "birleştiriciler sabit hale gelir" kısmı, c c {S, K, U, P} birleştiricileri için λx.c'yi Kc'ye çevirir. Sorun, bu birleştiricilerin polimorfik olması ve x'e bağlı bir türde kullanılabilmesidir; böyle bir tür bu çeviri ile korunamaz. Somut bir örnek olarak, ikinci bağımsız değişkenin türünün ilk bağımsız değişkene bağlı olduğu bir türde kullanılamayan λ (A : Set) → λ (a : A) → atür terimi (A : Set) → (a : A) → Aolarak çevrilir S(S(KS)(KK))(KK).
Anders Kaseorg

8

Sanırım "Parantez Soyutlaması" bazı durumlarda bağımlı türler için de işe yarıyor. Aşağıdaki makalenin 5. bölümünde bazı K ve S türlerini bulabilirsiniz:

Çirkin ama Anlamlı Tesadüfler
Bağımlı tür güvenli sözdizimi ve değerlendirme
Conor McBride, Strathclyde Üniversitesi, 2010

Bir lambda ifadesini kombinatoryal bir ifadeye dönüştürmek, kabaca doğal bir tümdengelim ispatını Hilbert tarzı bir kanıta dönüştürmeye karşılık gelir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.