Apakah ada cara untuk mewujudkan fungsi tipe ((a -> b) -> b) -> Entah ab?

18

Proposisi (P -> Q) -> Qdan P \/ Qsetara.

Apakah ada cara untuk menyaksikan kesetaraan ini di Haskell:

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 = ???

seperti yang

from . to = iddan to . from = id?


sumber
Tampak jelas bagi saya bahwa ini tidak mungkin, tetapi mungkin saya salah. Jika demikian, titik awal yang berguna adalah bahwa fungsi dengan tipe polimorfik ((a -> b) -> b)yang penuh isomorfik untuk a: satu-satunya implementasi yang mungkin adalah g f = f someHardcodedA.
amalloy
1
@amalloy ada kemungkinan implementasi lain:g = const someHardcodedB
Fyodor Soikin
Ah, tentu saja. Itu bisa aatau b. Masuk akal.
amalloy
1
Jika Haskell memiliki panggilan / cc, maka to f = callcc (\k -> k (Right (f (\a -> k (Left a)))))akan berhasil. (Ini adalah bukti klasik dari implikasinya.)
benrg

Jawaban:

14

Proposisi (P -> Q) -> Qdan P \/ Qsetara.

Ini benar dalam logika klasik, tetapi tidak dalam logika konstruktif.

Dalam logika konstruktif kita tidak memiliki hukum perantara yang dikecualikan , yaitu kita tidak dapat memulai pemikiran kita dengan "P benar atau P tidak benar".

Secara klasik kami beralasan seperti:

  • jika P benar (yaitu kita memiliki ( x :: P)) maka kembali Left x.
  • jika P salah, maka dalam bahasa Haskell kita akan memiliki nx :: P -> Voidfungsi. Kemudian absurd . nx :: P -> Q(kita dapat memuncak jenis apa pun, kita ambil Q) dan memanggil diberikan f :: (P -> Q) -> Q)dengan absurd . nxuntuk mendapatkan nilai jenis Q.

Masalahnya, bahwa tidak ada fungsi umum dari suatu tipe:

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

Untuk beberapa jenis konkret ada, misalnya Booldihuni sehingga kita bisa menulis

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

tetapi sekali lagi, secara umum kita tidak bisa.

phadej
sumber
9

Tidak, itu tidak mungkin. Pertimbangkan kasus khusus di mana Q = Void.

Either P Qkemudian Either P Void, yang isomorfik untuk 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

Karenanya, jika kita memiliki istilah fungsi

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

kita juga bisa memiliki istilah

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

Menurut korespondensi Curry-Howard, ini akan menjadi tautologi dalam logika intuitionistic :

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

Tetapi hal di atas adalah penghapusan negasi ganda, yang diketahui mustahil untuk dibuktikan dalam logika intuitionistic - karenanya merupakan kontradiksi. (Fakta bahwa kita dapat membuktikannya dalam logika klasik tidak relevan.)

(Catatan akhir: ini mengasumsikan bahwa keluar dari program Haskell berakhir. Tentu saja, menggunakan rekursi tak terbatas undefined,, dan cara-cara serupa untuk benar-benar menghindari untuk mengembalikan hasil, kita dapat menghuni jenis apa pun di Haskell.)

chi
sumber
4

Tidak, itu tidak mungkin, tapi agak halus. Masalahnya adalah bahwa variabel tipe adan bsecara universal dikuantifikasi.

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

adan bsecara universal diukur. Penelepon memilih jenis apa mereka, sehingga Anda tidak bisa hanya membuat nilai dari kedua jenis itu. Ini menyiratkan Anda tidak bisa hanya membuat nilai tipe Either a bsaat mengabaikan argumen f. Tetapi menggunakan fjuga tidak mungkin. Tanpa mengetahui tipe adan bapa, Anda tidak bisa membuat nilai tipe a -> buntuk diteruskan f. Tidak ada cukup informasi yang tersedia ketika jenis-jenis tersebut dikuantifikasi secara universal.

Sejauh mengapa isomorfisme tidak berfungsi di Haskell - apakah Anda yakin proposisi itu setara dalam logika intuitionist yang konstruktif? Haskell tidak menerapkan logika deduktif klasik.

Carl
sumber
2

Seperti yang telah ditunjukkan orang lain, ini tidak mungkin karena kita tidak memiliki hukum dari perantara yang dikecualikan. Biarkan saya membahasnya sedikit lebih eksplisit. Misalkan kita punya

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

dan kami mengatur b ~ Void. Lalu kita dapatkan

-- 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

Sekarang, mari kita buktikan negasi ganda hukum tengah yang dikecualikan sebagaimana diterapkan pada proposisi tertentu .

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

Jadi sekarang

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

lemjelas tidak bisa ada karena adapat menyandikan proposisi bahwa konfigurasi mesin Turing yang kebetulan saya pilih akan berhenti.


Mari kita verifikasi bahwa itu lemsudah cukup:

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)
dfeuer
sumber
0

Saya tidak tahu apa ini valid dalam hal logika, atau apa artinya untuk kesetaraan Anda, tapi ya mungkin untuk menulis fungsi seperti itu di Haskell.

Untuk membangun sebuah Either a b, kita membutuhkan suatu aatau bnilai. Kami tidak memiliki cara untuk membangun anilai, tetapi kami memiliki fungsi yang mengembalikan nilai byang bisa kami panggil. Untuk melakukan itu, kita perlu menyediakan fungsi yang mengubah suatu amenjadi b, tetapi mengingat jenis tidak diketahui kita bisa membuat fungsi yang mengembalikan konstanta b. Untuk mendapatkan bnilai itu, kita tidak bisa membangunnya dengan cara lain dari sebelumnya, jadi ini menjadi alasan melingkar - dan kita bisa menyelesaikannya dengan hanya membuat fixpoint :

to :: ((a -> b) -> b) -> Either a b
to f = let x = f (\_ -> x) in Right x
Bergi
sumber