eta-equence สำหรับฟังก์ชั่นที่ใช้งานร่วมกันได้กับการทำงาน seq ของ Haskell หรือไม่?


14

แทรก: สมมติว่า (\x -> ⊥) = ⊥ :: A -> BETA-เท่าเทียมเรามี

พิสูจน์: ⊥ = (\x -> ⊥ x)โดยกทพ. เทียบเท่าและ(\x -> ⊥ x) = (\x -> ⊥)โดยการลดภายใต้แลมบ์ดา

รายงาน Haskell 2010 ส่วน 6.2 ระบุseqฟังก์ชันด้วยสองสมการ:

seq :: a -> b -> b
seq ⊥ b = ⊥
seq ab = b, ถ้า a ≠⊥

จากนั้นจะอ้างว่า "เป็นผลให้⊥ไม่เหมือนกับ \ x -> ⊥เนื่องจาก seq สามารถใช้แยกแยะพวกเขาได้"

คำถามของฉันคือนั่นเป็นผลมาจากคำจำกัดความของseq?

อาร์กิวเมนต์นัยน่าจะเป็นที่seqจะ uncomputable seq (\x -> ⊥) b = ⊥ถ้า อย่างไรก็ตามฉันไม่สามารถพิสูจน์ได้ว่าสิ่งseqนี้จะไม่สามารถคำนวณได้ ดูเหมือนว่าฉันseqจะเป็นคนเดียวและต่อเนื่องซึ่งทำให้มันอยู่ในขอบเขตของการคำนวณ

อัลกอริทึมที่ใช้งานเช่น seq อาจทำงานได้โดยพยายามค้นหาบางxตำแหน่งf x ≠ ⊥โดยการระบุโดเมนfเริ่มต้นด้วย⊥ แม้ว่าการดำเนินการดังกล่าวแม้ว่าจะเป็นไปได้ แต่จะมีขนดกสวยเมื่อเราต้องการทำseqpolymorphic

มีหลักฐานว่าไม่มีการคำนวณseqที่ระบุ(\x -> ⊥)ด้วย⊥ :: A -> Bหรือไม่? อีกวิธีหนึ่งมีการก่อสร้างseqที่ไม่ระบุ(\x -> ⊥)ด้วย⊥ :: A -> B?

คำตอบ:


6

แรกให้เรามีความชัดเจนเกี่ยวกับวิธีการseqที่แตกต่างจากλ x :λx.

bottom :: a
bottom = bottom

eta :: a -> b
eta x = bottom

-- This terminates
fortytwo = seq eta 42

-- This does not terminate
infinity = seq bottom 42

มันจึงเป็นความจริงที่ว่าในการทดลอง Haskell และλ x มีความแตกต่างในเชิงปฏิบัติ มันเป็นความจริงและเป็นสิ่งที่ชัดเจนมากซึ่งคำนวณได้เพราะ Haskell คำนวณ มากมายเกี่ยวกับ Haskell คุณกำลังถามเกี่ยวกับถ้อยคำเฉพาะของเอกสาร Haskell ฉันอ่านมันบอกว่าควรจะตอบสนองทั้งสองสมการได้รับ แต่ทั้งสองสมการไม่เพียงพอสำหรับความหมายของ นี่คือเหตุผลที่: ฉันจะให้คุณสองรุ่น (พิมพ์เพียง) λแคลคูลัสซึ่งเป็นคำนวณและสร้างความพึงพอใจให้สม แต่ในหนึ่งในรูปแบบและλ x λx.seqseqseqλseqλx. เห็นด้วยในขณะที่พวกเขาไม่ทำ

ในรูปแบบโดเมนทฤษฎีง่ายๆที่ -expressions จะถูกตีความในโดเมนของฟังก์ชั่นอย่างต่อเนื่อง[ D E ]เรามี= λ x ชัด ใช้โดเมน Scott ที่มีประสิทธิภาพหรือบางอย่างเพื่อทำให้ทุกอย่างสามารถคำนวณได้ มันง่ายที่จะกำหนดในรูปแบบดังกล่าวλ[DE]=λx.seq

นอกจากนี้เรายังสามารถมีรูปแบบของแคลคูลัสที่แตกต่างและλ x แล้วแน่นอนη -rule ไม่สามารถถือ ตัวอย่างเช่นเราสามารถทำได้โดยการตีความฟังก์ชั่นในโดเมน[ D E ] เช่นโดเมนพื้นที่ฟังก์ชั่นที่มีการแนบด้านล่างพิเศษ ตอนนี้คือดีด้านล่างของ[ D E ] ขณะที่λ x เป็นองค์ประกอบที่อยู่เหนือมัน แอปพลิเคชันไม่สามารถแยกแยะได้เนื่องจากทั้งคู่ประเมินλseqλx.η[DE][DE]λx.ไม่ว่าสิ่งที่คุณนำไปใช้กับ (พวกเขาจะextensionally เท่ากัน) แต่เรามีเป็นแผนที่ระหว่างโดเมนและมันก็แยกแยะด้านล่างจากองค์ประกอบอื่น ๆ ทั้งหมดseq


1
มันเป็นความจริงทดลองว่าใน GHC และ / หรือ Hugs ⊥และλx.⊥ โชคดีที่ Haskell ไม่ได้ถูกกำหนดโดยการนำไปใช้งาน คำถามของฉันคือการชี้ให้เห็นว่า Haskell ไม่ได้ระบุไว้ในส่วนที่เกี่ยวกับ seq
Russell O'Connor

คุณสามารถให้การอ้างอิงถึงสิ่งที่คุณหมายถึงโดย "โดเมน Scott ที่มีประสิทธิภาพ" สันนิษฐานว่าไม่ได้หมายความว่าคำสั่งบางส่วนนั้นสามารถตัดสินใจได้ นอกจากนี้ STLC ไม่ใช่ polymorphic แต่ Haskell คือ โดยทั่วไปแล้ว Haskell จะถูกแปลความหมายใน System F หรือหนึ่งในอนุพันธ์ของมัน สิ่งนี้ส่งผลต่อการโต้แย้งของคุณอย่างไร
Russell O'Connor

ส่วนที่ 1.1.4 ของปริญญาเอกของฉัน dissertation andrej.com/thesis/thesis.pdfมีคำจำกัดความสั้น ๆ เกี่ยวกับโดเมน Scott ที่มีประสิทธิภาพและนี่เป็นครั้งแรกที่ Google ได้รับการเผยแพร่อย่างอิสระ
Andrej Bauer

2
หากคุณเขียนหลักฐานให้ฉันคุณจะได้รับการติดตั้ง Haskell 98 ซึ่งกฎ eta ช่วยให้ (foldr (\ ab -> fab) z xs) ได้รับการปรับให้เหมาะกับ (foldr fz xs) ทำให้ประสิทธิภาพ asymptotic เพิ่มขึ้นจาก O (n ^ 2) ถึง O (n) (ดูghc.haskell.org/trac/ghc/ticket/7436 ) มันจะช่วยให้ NewTypeWrapper ใน (NewTypeWrapper. f) ได้รับการปรับให้เหมาะสมโดยไม่บังคับให้ f ขยายการใช้งานและป้องกันไม่ให้มีการปรับค่า asymptotic ของ newTypes ใน GHC (เช่นการใช้ foldr เป็นต้น)
Russell O'Connor

1
ที่จริงแล้วคุณจะต้องให้แน่ใจว่าคอมไพเลอร์ของคุณมักจะดำเนินการเป็น⊥ นั่นคือคุณอาจถูกล่อลวงไปไม่ได้สัญญาอยู่เสมอและดังนั้นในหลักการλ x และจะเป็น "บางครั้งแตกต่าง" สถานการณ์ที่อันตรายมาก เพื่อให้แน่ใจว่าไม่ใช่กรณีนี้คุณจะต้องใช้วิธีที่ชาญฉลาดซึ่งเกี่ยวข้องกับการวางไข่กระบวนการจำนวนมากอย่างไม่สิ้นสุดซึ่งแต่ละการใช้ฟังก์ชั่นของคุณกับองค์ประกอบพื้นฐาน หากกระบวนการใด ๆ ยุติลงก็อาจดำเนินการต่อไป มันน่าสนใจที่จะดูว่าเราสามารถทำตามลำดับได้ไหม อืมมม λx.λx.seqseq
Andrej Bauer

2

โปรดทราบว่าข้อกำหนดseqที่คุณอ้างไม่ใช่ข้อกำหนดของมัน ในการอ้างอิงรายงาน Haskell "ฟังก์ชัน seq ถูกกำหนดโดยสมการ : [จากนั้นสมการที่คุณให้]"

อาร์กิวเมนต์ที่แนะนำนั้นดูเหมือนว่า seq จะไม่สามารถคำนวณได้ถ้า seq (\ x -> ⊥) b = ⊥

seqพฤติกรรมดังกล่าวจะเป็นการละเมิดข้อกำหนดของ

ที่สำคัญเนื่องจากseqpolymorphic seqไม่สามารถกำหนดในรูปของ deconstructors (การจับคู่แบบโปรเจคชั่น / รูปแบบ ฯลฯ ) ในพารามิเตอร์สองตัวใดตัวหนึ่ง

มีหลักฐานว่าไม่มี seq ที่คำนวณได้ที่ระบุ (\ x -> ⊥) กับ⊥ :: A -> B หรือไม่?

ถ้าseq' (\x -> ⊥) bมีใครคิดว่าเราสามารถใช้พารามิเตอร์ตัวแรก (ซึ่งเป็นฟังก์ชั่น) กับค่าบางส่วนจากนั้นรับออก แต่seqไม่สามารถระบุพารามิเตอร์แรกด้วยค่าฟังก์ชัน (แม้ว่าจะเป็นพารามิเตอร์สำหรับการใช้งานบางอย่างseq) เนื่องจากพารามิเตอร์ polymorphic ประเภทของพารามิเตอร์ พารามิเตอร์หมายความว่าเราไม่รู้อะไรเกี่ยวกับพารามิเตอร์ นอกจากนี้seqไม่สามารถใช้นิพจน์และตัดสินใจว่า "นี่คือ⊥หรือไม่" (เทียบกับปัญหาการหยุดชะงัก) seqสามารถลองประเมินได้เท่านั้นและแยกตัวไปที่⊥

อะไรseqคือการประเมินค่าพารามิเตอร์แรก (ไม่ครบถ้วน แต่เป็น "รูปแบบปกติของส่วนหัวที่อ่อนแอ" [1], คือตัวสร้างที่อยู่ด้านบนสุด) จากนั้นส่งคืนพารามิเตอร์ตัวที่สอง ถ้าพารามิเตอร์แรกที่จะเกิดขึ้น(เช่นยกเลิกการคำนวณที่ไม่ใช่) แล้วจะทำให้การประเมินที่ไม่ได้บอกเลิกและทำให้seqseq ⊥ a = ⊥

[1] ทฤษฎีบทอิสระในการปรากฏตัวของ seq - โยฮันน์, Voigtlander http://www.iai.uni-bonn.de/~jv/p76-voigtlaender.pdf


ข้อกำหนดที่ฉันให้สำหรับ seq คือคำจำกัดความของ seq เพราะนั่นคือสิ่งที่รายงาน Haskell 2010 ระบุไว้ในส่วนที่ 6.2 คำจำกัดความการดำเนินงานของ seq ของคุณไม่ได้รับการสนับสนุนโดยรายงาน Haskell 2010: คำว่า "รูปแบบปกติหัว" จะเกิดขึ้นเพียงครั้งเดียวในรายงานในบริบทที่แตกต่างกันโดยสิ้นเชิง นอกจากนี้ยังไม่สอดคล้องกับความเข้าใจของฉันที่ GHC มักจะลดอาร์กิวเมนต์ที่สองเป็น seq ก่อนอาร์กิวเมนต์แรกหรืออาร์กิวเมนต์แรกจะไม่ลดลงเลยเพราะตัววิเคราะห์ความเข้มงวดได้พิสูจน์แล้วว่าไม่ใช่ด้านล่างแบบคงที่
Russell O'Connor

Parametricity ไม่ได้บอกว่าเราไม่สามารถใช้ deconstructors ใด ๆ โดยตรงและไม่ได้บอกว่าเราไม่สามารถระบุพารามิเตอร์แรกด้วยค่าฟังก์ชันได้ พารามิเตอร์ทั้งหมดบอกว่าสำหรับแคลคูลัส polymorphic แลมบ์ดากับ fixpoints คือ seq สามารถดูดซับฟังก์ชั่นที่เข้มงวดหรือโดยทั่วไปความสัมพันธ์ที่เข้มงวดบางอย่างสำหรับคำที่มี seq ฉันยอมรับว่ามีความเป็นไปได้ที่พาราเมทริกตี้อาจถูกใช้เพื่อพิสูจน์ (\ x -> ⊥) & ne; ⊥ แต่ฉันต้องการดูหลักฐานที่เข้มงวด
Russell O'Connor

ในกรณีของฟังก์ชั่นf : forall a . a -> T(ซึ่งTเป็นประเภทอื่น ๆ ) จากนั้นfไม่สามารถใช้ deconstructors ใด ๆ กับการโต้แย้งครั้งแรกเพราะมันไม่ทราบว่า deconstructors ใดที่จะใช้ เราไม่สามารถทำ "กรณี" กับประเภท ฉันพยายามปรับปรุงคำตอบข้างต้น (รวมถึงการอ้างถึงข้อมูลเกี่ยวกับseqการประเมินแบบฟอร์มปกติ)
dorchard

ฉันสามารถลองทำการพิสูจน์อย่างเข้มงวดในภายหลังหากฉันหาเวลา (การใช้ความสัมพันธ์ในสไตล์ของ Reynolds อาจเป็นวิธีที่ดี)
dorchard

@ RussellO'Connor: คำอธิบายของ seq ไม่ได้ "ไม่สอดคล้อง" กับพฤติกรรมเหล่านั้นเป็นเพียงข้อกำหนดการดำเนินงาน (และพฤติกรรมคือการปรับให้เหมาะสมซึ่งไม่เปลี่ยนผลลัพธ์สุดท้าย)
Blaisorblade

2

λx.λx.

Samson Abramsky พิจารณาปัญหานี้มานานแล้วและได้เขียนบทความที่ชื่อว่า " The Lazy Lambda แคลคูลัส " ดังนั้นหากคุณต้องการคำจำกัดความที่เป็นทางการนี่คือที่ที่คุณอาจมอง


1
เห็นได้ชัดว่ารายละเอียดเหล่านี้ถูกกำหนดโดยการดึงลงใน "Haskell kernel" เท่านั้น มันกำหนดไว้ที่ไหน? รายงานกล่าวว่าในวินาที 1.2 : "แม้ว่าเคอร์เนลจะไม่ได้รับการระบุอย่างเป็นทางการ แต่ก็เป็นตัวแปรที่ค่อนข้าง sugared ของแคลคูลัสแลมบ์ดาที่มีความหมายเชิงตรงไปตรงมา denotational การแปลของโครงสร้างประโยคแต่ละครั้งลงในเคอร์เนลจะได้รับเมื่อมีการแนะนำไวยากรณ์"
Blaisorblade

รายงาน Haskell 2010 บอกว่าเหมือนกันอย่างน่าอัศจรรย์
Blaisorblade

ขอบคุณสำหรับการอ้างอิงถึง Abramsky! ฉันอ่านมันเพื่อดูว่ามันตอบคำถามได้อย่างไรและฉันได้คำตอบต่อไปนี้: cstheory.stackexchange.com/a/21732/989
Blaisorblade

2

พิสูจน์ว่าλ x Ω ‌ ≠Ω in เป็นหนึ่งในเป้าหมายที่อับรามสกี้วางไว้สำหรับทฤษฎีแคลคูลัสแลมบ์ดาสันหลังยาวของเขา (หน้า 2 จากกระดาษของเขาซึ่งถูกอ้างถึงโดยอูเดย์เรดดี้) เพราะพวกเขาทั้งคู่อยู่ในรูปแบบปกติที่อ่อนแอ ตามนิยาม 2.7 เขากล่าวอย่างชัดเจนว่ากทพ. ลดλ x M x → M โดยทั่วไปไม่ถูกต้อง แต่เป็นไปได้ถ้า M ยุติในทุกสภาพแวดล้อม นี่ไม่ได้หมายความว่า M จะต้องเป็นฟังก์ชันทั้งหมด - เฉพาะที่การประเมิน M ต้องยุติ (โดยการลดแลมบ์ดาเป็นต้น)

คำถามของคุณดูเหมือนจะมีแรงจูงใจจากความกังวลในทางปฏิบัติ (การปฏิบัติงาน) อย่างไรก็ตามถึงแม้ว่ารายงาน Haskell อาจจะชัดเจนน้อยกว่า แต่ฉันสงสัยว่ามันเท่ากับλ x ith ‌ ด้วย⊥จะสร้างการใช้งานที่มีประโยชน์ของ Haskell; ไม่ว่าจะเป็นการดำเนินการของ Haskell '98 หรือไม่เป็นที่ถกเถียงกัน แต่ได้รับคำพูดเป็นที่ชัดเจนว่าผู้เขียนตั้งใจให้เป็นจริง

ในที่สุด seq ของวิธีการสร้างองค์ประกอบสำหรับประเภทการป้อนข้อมูลโดยพลการ? (ฉันรู้ว่า QuickCheck กำหนดประเภทของ Arbitrary สำหรับสิ่งนั้น แต่คุณไม่ได้รับอนุญาตให้เพิ่มข้อ จำกัด ดังกล่าวที่นี่) สิ่งนี้ละเมิดพาราเมตริก

อัปเดต : ฉันไม่สามารถจัดการรหัสนี้ได้ถูกต้อง (เพราะฉันไม่ค่อยคล่องแคล่วใน Haskel) และการแก้ไขนี้ดูเหมือนว่าจะต้องใช้runSTพื้นที่ซ้อนกัน ฉันพยายามใช้เซลล์อ้างอิงเดียว (ใน ST monad) เพื่อบันทึกองค์ประกอบตามอำเภอใจดังกล่าวอ่านในภายหลังและทำให้ใช้ได้อย่างเป็นสากล Parametricity พิสูจน์ว่าbreak_parametricityไม่สามารถกำหนดด้านล่างได้ (ยกเว้นกลับด้านล่างเช่นข้อผิดพลาด) ในขณะที่มันสามารถกู้คืนองค์ประกอบที่ seq เสนอของคุณจะสร้าง

import Control.Monad.ST
import Data.STRef
import Data.Maybe

produce_maybe_a :: Maybe a
produce_maybe_a = runST $ do { cell <- newSTRef Nothing; (\x -> writeSTRef cell (Just x) >> return x) `seq` (readSTRef cell) }

break_parametricity :: a
break_parametricity = fromJust produce_maybe_a

ฉันต้องยอมรับว่าฉันคลุมเครือเล็กน้อยเกี่ยวกับการพิสูจน์แบบพาราเมทริกที่จำเป็นที่นี่ แต่การใช้พาราเมตริกแบบไม่เป็นทางการเป็นมาตรฐานใน Haskell; แต่ฉันได้เรียนรู้จากงานเขียนของ Derek Dreyer ว่าทฤษฎีที่ต้องการนั้นได้ผลอย่างรวดเร็วในช่วงหลายปีที่ผ่านมา

การแก้ไข:

  • ฉันไม่แน่ใจด้วยซ้ำว่าคุณต้องการส่วนขยายเหล่านั้นซึ่งได้รับการศึกษาสำหรับภาษาที่มีลักษณะคล้าย ML, ที่จำเป็นและไม่พิมพ์หรือว่าทฤษฎีคลาสสิกของพาราเมทริกตี้ครอบคลุม Haskell
  • นอกจากนี้ฉันยังพูดถึง Derek Dreyer เพียงเพราะฉันเพิ่งเจองานของ Uday Reddy - ฉันได้เรียนรู้เกี่ยวกับเรื่องนี้เมื่อไม่นานมานี้จาก "แก่นแท้ของ Reynolds" (ฉันเพิ่งเริ่มอ่านวรรณคดีเรื่องพาราเมตริกเมื่อเดือนที่แล้ว)

การประเมิน(\x -> writeSTRef cell (Just x) >> return x)อินพุตแบบสุ่มไม่ได้ดำเนินการเขียนไปยังเซลล์ เฉพาะคำสั่ง ST ที่ทำให้เป็นลำดับที่ส่งเข้าไปrunSTเท่านั้นที่จะถูกดำเนินการ ในทำนองเดียวกันการmain = (putStrLn "Hello") `seq` (return ())พิมพ์จะไม่พิมพ์สิ่งใดบนหน้าจอ
Russell O'Connor

@ RussellO'Connor แน่นอนว่าคุณพูดถูก - การทดสอบนั้นยากเนื่องจาก seq ไม่มีพฤติกรรมที่เราพูดถึง แต่ฉันก็ยังคิดว่าองค์ประกอบที่สร้างการแบ่งพาราเมตริกต่อ se ฉันจะลองแก้ไขคำตอบเพื่อเป็นตัวอย่าง
Blaisorblade

อืมการแก้ไขคำตอบที่ชัดเจนนั้นต้องการการซ้อนพื้นที่ runST และใช้เซลล์จากขอบเขตด้านนอกในส่วนด้านใน แต่นั่นไม่ได้รับอนุญาต
Blaisorblade
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.