บทเรียนส่วนใหญ่เกี่ยวกับแลมบ์ดาแคลคูลัสให้ตัวอย่างที่ฟังก์ชัน Integers และ Booleans ที่เป็นบวกสามารถแสดงได้ -1 แล้วฉันล่ะ
บทเรียนส่วนใหญ่เกี่ยวกับแลมบ์ดาแคลคูลัสให้ตัวอย่างที่ฟังก์ชัน Integers และ Booleans ที่เป็นบวกสามารถแสดงได้ -1 แล้วฉันล่ะ
คำตอบ:
เข้ารหัสหมายเลขและคู่ตามธรรมชาติตามที่อธิบายโดย jmad
แทนจำนวนเต็มเป็นคู่ของตัวเลขธรรมชาติเช่นที่b จากนั้นคุณสามารถกำหนดการดำเนินการตามปกติกับจำนวนเต็มเป็น (โดยใช้สัญกรณ์ Haskell สำหรับ -calculus):
neg = \k -> (snd k, fst k)
add = \k m -> (fst k + fst m, snd k + snd m)
sub = \k m -> add k (neg m)
mul = \k m -> (fst k * fst m + snd k * snd m, fst k * snd m + snd k * fst m)
กรณีของจำนวนเชิงซ้อนคล้ายกันในแง่ที่ว่าจำนวนเชิงซ้อนถูกเข้ารหัสเป็นคู่ของจำนวนจริง แต่คำถามที่ซับซ้อนมากขึ้นคือการเข้ารหัสซ้ำได้อย่างไร ที่นี่คุณต้องทำงานเพิ่มเติม:
การเข้ารหัสซ้ำเป็นงานจำนวนมากและคุณไม่ต้องการที่จะทำจริงใน -calculus แต่ดูตัวอย่างไดเรกทอรีย่อยของMarshallสำหรับการใช้งาน reals อย่างง่าย ๆ ใน Haskell ล้วนๆ ซึ่งอาจในหลักการที่จะได้รับการแปลบริสุทธิ์λแคลคูลัสetc/haskell
i:ℤ
, x:a
, f,u,s:a→a
, p:(a→a,a→a)
] ถ้าคุณเข้ารหัสℤเป็น(Sign,ℕ)
แล้วให้คู่ของฟังก์ชั่น(s,f)
เป็นp
ระยะที่λi.λp.λx.(fst i) (fst p) id ((snd i) (snd p) x)
จะผลิตอย่างใดอย่างหนึ่งf(…f(x)…)
หรือs(f(…f(x)…))
(ถ้าผลเป็นลบ) หากคุณเข้ารหัสℤเป็น(ℕ,ℕ)
คุณจะต้องฟังก์ชั่นที่มีการผกผัน - การรับคู่(f,u)
และx
ฟังก์ชั่นλi.λp.λx.(snd i)(snd p)((fst i)(fst p) x)
จะผลิตu(…u(f(…f(x)…))…)
ซึ่งจะทำให้f
การประยุกต์ใช้ครั้งเพื่อi
x
การทำงานในบริบทที่แตกต่างกัน (ผลที่ได้คือ "พลิก" || f
กลับไม่ได้)
fold . ctor
ไว้สำหรับผู้สร้างและประเภทนั้นfold
( r
) (ซึ่งเป็นสาเหตุสำหรับประเภทแบบเรียกซ้ำข้อมูลจะ "หักล้างด้วยตัวเอง" สำหรับประเภทที่ไม่เกิดซ้ำมันเหมือนกับการcase
จับคู่รูปแบบ / มากกว่า)
แลมบ์ดาแคลคูลัสสามารถเข้ารหัสโครงสร้างข้อมูลและประเภทพื้นฐานส่วนใหญ่ได้ ตัวอย่างเช่นคุณสามารถเข้ารหัสคู่ของคำศัพท์ที่มีอยู่ในแคลคูลัสแลมบ์ดาโดยใช้การเข้ารหัสของโบสถ์เดียวกับที่คุณมักจะเห็นเพื่อเข้ารหัสจำนวนเต็มและบูลีนที่ไม่จำเป็น:
FST = λพี P ( λ x Y . x ) snd = λพี p ( λ x y . y )
จากนั้นทั้งคู่คือP = ( จับคู่ ข)และถ้าคุณต้องการที่จะได้รับกลับและขคุณสามารถทำ( FST P )และ ( snd P )
นั่นหมายความว่าคุณสามารถแสดงจำนวนเต็มบวกและลบด้วยคู่ได้อย่างง่ายดาย: เครื่องหมายทางด้านซ้ายและค่าสัมบูรณ์ทางด้านขวา เครื่องหมายเป็นบูลีนที่ระบุว่าหมายเลขเป็นบวกหรือไม่ ด้านขวาเป็นจำนวนธรรมชาติโดยใช้การเข้ารหัสของคริสตจักร
และตอนนี้คุณมีจำนวนเต็มสัมพัทธ์ การคูณนั้นง่ายต่อการกำหนดคุณแค่ต้องใช้ฟังก์ชันกับเครื่องหมายและการคูณจำนวนธรรมชาติบนค่าสัมบูรณ์:
ในการกำหนดการเพิ่มคุณต้องเปรียบเทียบตัวเลขธรรมชาติสองตัวและใช้การลบเมื่อสัญญาณแตกต่างกันดังนั้นนี่ไม่ใช่คำศัพท์ แต่คุณสามารถปรับได้ถ้าคุณต้องการ:
แต่การลบนั้นง่ายต่อการกำหนด:
ย่อยℤ = λข เพิ่มℤ (a)(ลบℤ b)
เมื่อคุณมีจำนวนเต็มบวกและเชิงลบที่คุณสามารถกำหนดเลขที่ซับซ้อนได้อย่างง่ายดายมาก: มันเป็นเพียงแค่คู่ของสองจำนวนเต็มซึ่งหมายถึง+ ขฉัน นอกจากนี้การเติมจุดและการคูณเป็นปกติแต่ฉันจะไม่เขียนมันควรจะง่าย: