((A -> b) -> b) -> Her iki tipte bir fonksiyon gerçekleştirmenin bir yolu var mı?


18

Öneriler (P -> Q) -> Qve P \/ Qeşdeğerdir.

Haskell'de bu denkliğe şahit olmanın bir yolu var mı:

from :: Either a b -> ((a -> b) -> b)
from x = case x of
         Left a -> \f -> f a
         Right b -> \f -> b

to :: ((a -> b) -> b) -> Either a b
to = ???

öyle ki

from . to = idve to . from = id?


Bunun imkansız olduğu açık görünüyor, ama belki de yanılıyorum. Eğer öyleyse, yararlı bir başlangıç ​​noktası, tam olarak polimorfik tipte bir fonksiyonun ((a -> b) -> b)izomorfik olmasıdır a: olası tek uygulama g f = f someHardcodedA.
amalloy

1
@amalloy başka bir uygulama daha var:g = const someHardcodedB
Fyodor Soikin

Ah, elbette. Ya aya b. Mantıklı.
amalloy

1
Haskell'in / cc çağrısı to f = callcc (\k -> k (Right (f (\a -> k (Left a)))))olsaydı işe yarardı. (Bu, çıkarımın geçerli bir klasik kanıtıdır.)
benrg

Yanıtlar:


14

Öneriler (P -> Q) -> Qve P \/ Qeşdeğerdir.

Bu klasik mantık için geçerlidir, fakat yapıcı mantık için geçerli değildir.

Yapıcı mantıkta dışlanmış ortada bir yasa yoktur , yani düşüncemize "P doğru ya da P doğru değil" ile başlayamayız.

Klasik olarak mantık yürütüyoruz:

  • P doğruysa (yani biz ( x :: P)) sonra geri dönün Left x.
  • eğer P yanlışsa, o zaman Haskell'de nx :: P -> Voidfonksiyonumuz olur. Sonra absurd . nx :: P -> Q(biz her türlü zirve, biz almak Q) ve verilen çağrı f :: (P -> Q) -> Q)ile absurd . nxtürünün değerini elde etmek Q.

Sorun, bir türün genel işlevi olmadığı için:

lem :: forall p. Either p (p -> Void)

Bazı somut türleri için örneğin orada Boolbiz yazabiliriz böylece yaşadığı

lemBool :: Either Bool (Bool -> Void)
lemBool = Left True -- arbitrary choice

ama yine de, genel olarak yapamayız.


9

Hayır, bu imkansız. Burada özel durumu düşünün Q = Void.

Either P Qo zaman Either P Voidizomorfiktir P.

iso :: P -> Either P Void
iso = Left

iso_inv :: Either P Void -> P
iso_inv (Left p)  = p
iso_inv (Right q) = absurd q

Dolayısıyla, eğer bir işlev terimi olsaydı

impossible :: ((P -> Void) -> Void) -> Either P Void

ayrıca bir terimimiz olabilir

impossible2 :: ((P -> Void) -> Void) -> P
impossible2 = iso_inv . impossible

Curry-Howard yazışmalarına göre, bu sezgisel mantıkta bir totoloji olurdu :

((P -> False) -> False) -> P

Ancak yukarıdaki, sezgisel mantıkta kanıtlanmasının imkansız olduğu bilinen çift olumsuzluk ortadan kaldırmasıdır - dolayısıyla bir çelişki. ( Klasik mantıkta ispatlayabileceğimiz gerçeği önemli değildir.)

(Son not: Bu, Haskell programının sona erdiğini varsayar. Tabii ki, sonsuz özyineleme kullanarak undefinedve bir sonucu döndürmekten gerçekten kaçınmanın benzer yollarını kullanarak, Haskell'deki herhangi bir türde yaşayabiliriz.)


4

Hayır, bu mümkün değil, ama biraz ince. Sorun türü değişkenleri ave bevrensel olarak nicel olmasıdır.

to :: ((a -> b) -> b) -> Either a b
to f = ...

ave bevrensel olarak nicelendirilir. Arayan kişi ne tür olduğunu seçer, böylece her iki türden bir değer oluşturamazsınız. Bu Either a b, argümanı yok sayarken yalnızca bir tür değer oluşturamayacağınız anlamına gelir f. Ancak kullanmak fda imkansız. Hangi tür ave ne olduğunu bilmeden b, a -> bgeçilecek bir tür değeri oluşturamazsınız f. Türler evrensel olarak nicelleştirildiğinde yeterli bilgi yoktur.

İzomorfizmin Haskell'de neden işe yaramadığı kadarıyla - bu önermelerin yapıcı bir sezgisel mantıkta eşdeğer olduğundan emin misiniz? Haskell klasik bir tümdengelimli mantık uygulamamaktadır.


2

Diğerlerinin de belirttiği gibi, bu imkansızdır çünkü dışlanan ortadaki yasaya sahip değiliz. Bunu biraz daha açık bir şekilde ele alalım. Varsayalım

bogus :: ((a -> b) -> b) -> Either a b

ve biz yola çıktık b ~ Void. Sonra anlıyoruz

-- chi calls this `impossible2`.
double_neg_elim :: ((a -> Void) -> Void) -> a
bouble_neg_elim f = case bogus f of
             Left a -> a
             Right v -> absurd v

Şimdi, belirli bir teklife uygulandığı gibi , hariç tutulan ortadaki yasanın çifte olumsuzlanmasını kanıtlayalım .

nnlem :: forall a. (Either a (a -> Void) -> Void) -> Void
nnlem f = not_not_a not_a
  where
    not_a :: a -> Void
    not_a = f . Left

    not_not_a :: (a -> Void) -> Void
    not_not_a = f . Right

Peki şimdi

lem :: Either a (a -> Void)
lem = double_neg_elim nnlem

lemaçıkça var olamaz çünkü aseçtiğim herhangi bir Turing makinesi yapılandırmasının duracağı önerisini kodlayabilir.


Bunun lemyeterli olduğunu doğrulayalım :

bogus :: forall a b. ((a -> b) -> b) -> Either a b
bogus f = case lem @a of
  Left a -> Left a
  Right na -> Right $ f (absurd . na)

0

Bunun mantık açısından geçerli olup olmadığı veya eşdeğerliğiniz için ne anlama geldiği hakkında hiçbir fikrim yok, ancak evet, Haskell'de böyle bir işlev yazmak mümkündür.

An oluşturmak için Either a bya ya ada bir bdeğere ihtiyacımız var . Bir adeğer oluşturmak için herhangi bir yolumuz yok, ancak bçağırabileceğimiz bir değer döndüren bir fonksiyonumuz var . Bunu yapmak için, biz dönüştürür bir o bir işlevi sağlamanız gerekmektedir abir içine biyi bir işlev döndürdüğü sabit hale de ancak tipleri verilen yapabiliriz bilinmemektedir b. Bu bdeğeri elde etmek için, öncekinden başka bir şekilde inşa edemeyiz, bu da dairesel bir akıl yürütme haline gelir - ve bunu sadece bir düzeltme noktası oluşturarak çözebiliriz :

to :: ((a -> b) -> b) -> Either a b
to f = let x = f (\_ -> x) in Right x
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.