มีวิธีที่จะตระหนักถึงฟังก์ชั่นของประเภท ((a -> b) -> b) -> ab ทั้งสอง?


18

ข้อเสนอ(P -> Q) -> QและP \/ Qเทียบเท่า

มีวิธีที่จะเห็นความเท่าเทียมกันนี้ใน 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 = ???

ดังนั้น

from . to = idและto . from = id?


เห็นได้ชัดสำหรับฉันว่านี่เป็นไปไม่ได้ แต่บางทีฉันผิด ถ้าเป็นเช่นนั้นเป็นจุดเริ่มต้นที่มีประโยชน์ก็คือฟังก์ชั่นที่มีประเภท polymorphic thefully ((a -> b) -> b)เป็น isomorphic ไปa: g f = f someHardcodedAการดำเนินงานที่เป็นไปได้เพียงอย่างเดียวคือ
amalloy

1
@amalloy มีการใช้งานที่เป็นไปได้อีกอย่างหนึ่ง:g = const someHardcodedB
Fyodor Soikin

อ่าแน่นอน มันเป็นอย่างใดอย่างหนึ่งหรือa bมีเหตุผล.
amalloy

1
หาก Haskell มีสาย / ซีซีก็to f = callcc (\k -> k (Right (f (\a -> k (Left a)))))จะทำงานได้ (นี่เป็นข้อพิสูจน์แบบดั้งเดิมที่ถูกต้องเกี่ยวกับความหมาย)
7161

คำตอบ:


14

ข้อเสนอ(P -> Q) -> QและP \/ Qเทียบเท่า

นี่คือความจริงในตรรกะคลาสสิก แต่ไม่ได้อยู่ในตรรกะเชิงสร้างสรรค์

ในเชิงตรรกะเราไม่ได้มีกฎของการแยกกลางคือเราไม่สามารถเริ่มต้นความคิดของเราด้วย "ทั้ง P เป็นจริงหรือ P ไม่เป็นความจริง"

คลาสสิกเรามีเหตุผลที่ชอบ:

  • ถ้า P เป็นจริง (เช่นเรามี ( x :: P)) Left xแล้วกลับมา
  • ถ้า P เป็นเท็จจากนั้นใน Haskell พูดว่าเราต้องการnx :: P -> Voidฟังก์ชั่น จากนั้นabsurd . nx :: P -> Q(เราสามารถสูงสุดประเภทใดที่เราใช้เวลาQ) และโทรให้f :: (P -> Q) -> Q)กับที่จะได้รับค่าของชนิดabsurd . nxQ

ปัญหาว่าไม่มีฟังก์ชั่นทั่วไปของประเภท:

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

สำหรับคอนกรีตบางประเภทนั้นมีอยู่เช่นBoolมีคนอาศัยอยู่ดังนั้นเราจึงสามารถเขียนได้

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

แต่โดยทั่วไปเราไม่สามารถ


9

ไม่มันเป็นไปไม่ได้ Q = Voidพิจารณากรณีพิเศษที่

Either P Qเป็นแล้วEither P Voidซึ่งเป็น isomorphic 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

ดังนั้นถ้าเรามีฟังก์ชั่นระยะ

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

เราอาจมีคำหนึ่งคำ

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

ตามที่แกงกะหรี่ - โฮเวิร์ดจดหมายนี่จะเป็นคำพูดซ้ำซากในตรรกะปรีชา :

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

แต่ข้างต้นคือการคัดค้านการลบล้างสองเท่าซึ่งเป็นที่รู้จักกันดีว่าเป็นไปไม่ได้ที่จะพิสูจน์ในตรรกะของสัญชาตญาณ - จึงขัดแย้งกัน (ความจริงที่ว่าเราสามารถพิสูจน์ได้ในตรรกะคลาสสิกไม่เกี่ยวข้อง)

(หมายเหตุสุดท้าย: นี่ถือว่าโปรแกรม Haskell ยุติแน่นอนว่าใช้การเรียกซ้ำแบบไม่สิ้นสุดundefinedและวิธีที่คล้ายกันเพื่อหลีกเลี่ยงการส่งคืนผลลัพธ์จริง ๆ เราสามารถอาศัยอยู่ใน Haskell ทุกประเภท)


4

ไม่มันเป็นไปไม่ได้ แต่มันบอบบางไปหน่อย ปัญหาคือว่าตัวแปรประเภทaและbมีปริมาณในระดับสากล

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

aและbเป็นปริมาณในระดับสากล ผู้เรียกเลือกว่าเป็นประเภทใดดังนั้นคุณจึงไม่สามารถสร้างมูลค่าเป็นประเภทใดประเภทหนึ่งได้ ซึ่งหมายความว่าคุณไม่สามารถเพียงแค่สร้างค่าของชนิดในขณะที่ละเลยการโต้แย้งEither a b fแต่การใช้fก็เป็นไปไม่ได้เช่นกัน คุณไม่สามารถสร้างคุณค่าประเภทที่จะส่งผ่านไปโดยไม่ทราบว่าเป็นชนิดใดaและbคืออะไร มีข้อมูลไม่เพียงพอเมื่อมีการจัดประเภทเป็นสากลa -> bf

ตราบใดที่ว่าทำไมมอร์ฟิซึ่มไม่ทำงานในแฮสเค็ลล์ - คุณแน่ใจหรือไม่ว่าข้อเสนอเหล่านั้นมีความเท่าเทียมกันในตรรกะเชิงสัญชาตญาณที่สร้างสรรค์ Haskell ไม่ได้ใช้ตรรกะแบบนิรนัยแบบคลาสสิก


2

ดังที่คนอื่น ๆ ชี้ว่าสิ่งนี้เป็นไปไม่ได้เพราะเราไม่มีกฎหมายของคนกลางที่ถูกกีดกัน ขอผมดูอย่างละเอียดอีกหน่อย สมมติว่าเรามี

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

b ~ Voidและเราตั้ง จากนั้นเราจะได้รับ

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

ตอนนี้ขอพิสูจน์คู่ปฏิเสธของกฎหมายของยกเว้นตรงกลางนำไปใช้เป็นข้อเสนอที่เฉพาะเจาะจง

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

ดังนั้นตอนนี้

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

lemไม่สามารถชัดเจนได้เพราะaสามารถเข้ารหัสโจทย์ที่ว่าการกำหนดค่าเครื่องทัวริงใดที่ฉันเลือกจะหยุด


ตรวจสอบว่าlemเพียงพอแล้ว

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

ฉันไม่รู้ว่ามันถูกต้องในแง่ของตรรกะหรือสิ่งที่มีความหมายสำหรับการเทียบเท่าของคุณ แต่ใช่มันเป็นไปได้ที่จะเขียนฟังก์ชันดังกล่าวใน Haskell

เพื่อสร้างEither a bเราต้องอย่างใดอย่างหนึ่งaหรือbคุ้มค่า เราไม่มีวิธีใดในการสร้างaค่า แต่เรามีฟังก์ชั่นที่คืนค่าbที่เราสามารถเรียกได้ ต้องการทำเช่นนั้นเราจำเป็นต้องจัดหาฟังก์ชั่นที่แปลงaเป็นแต่ให้ชนิดเป็นที่รู้จักเราสามารถที่ดีที่สุดให้ฟังก์ชั่นที่ให้ผลตอบแทนคงที่b bเพื่อให้ได้bค่านั้นเราไม่สามารถสร้างมันได้อย่างอื่นก่อนหน้านี้ดังนั้นจึงกลายเป็นการให้เหตุผลแบบวงกลม - และเราสามารถแก้ไขได้โดยเพียงแค่สร้างfixpoint :

to :: ((a -> b) -> b) -> Either a b
to f = let x = f (\_ -> x) in Right x
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.