การแทนตัวเลขเชิงลบและจำนวนเชิงซ้อนโดยใช้แคลคูลัสแลมบ์ดา


14

บทเรียนส่วนใหญ่เกี่ยวกับแลมบ์ดาแคลคูลัสให้ตัวอย่างที่ฟังก์ชัน Integers และ Booleans ที่เป็นบวกสามารถแสดงได้ -1 แล้วฉันล่ะ

คำตอบ:


18

เข้ารหัสหมายเลขและคู่ตามธรรมชาติตามที่อธิบายโดย jmad

แทนจำนวนเต็มเป็นคู่ของตัวเลขธรรมชาติเช่นที่b จากนั้นคุณสามารถกำหนดการดำเนินการตามปกติกับจำนวนเต็มเป็น (โดยใช้สัญกรณ์ Haskell สำหรับ -calculus):k(a,b)k=abλ

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)

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

  1. เข้ารหัสเหตุผลจำนวนเป็นคู่ที่เป็นจำนวนเต็มเป็นธรรมชาติและA)q(k,a)kaq=k/(1+a)
  2. เข้ารหัสจำนวนจริงโดยฟังก์ชั่นดังกล่าวว่าสำหรับทุกธรรมชาติk N , F kถอดรหัสจำนวนจริงคิวดังกล่าวว่า| x - q | < 2 - k ในคำอื่น ๆ จริงจะถูกเข้ารหัสเป็นลำดับของ rationals บรรจบกับมันในอัตราที่k 2 - kxfkNfkq|xq|<2kk2k

การเข้ารหัสซ้ำเป็นงานจำนวนมากและคุณไม่ต้องการที่จะทำจริงใน -calculus แต่ดูตัวอย่างไดเรกทอรีย่อยของMarshallสำหรับการใช้งาน reals อย่างง่าย ๆ ใน Haskell ล้วนๆ ซึ่งอาจในหลักการที่จะได้รับการแปลบริสุทธิ์λแคลคูลัสλetc/haskellλ


1
Wow =) ฉันสงสัยอย่างสังหรณ์ใจว่าอะไรหมายถึง ... ตัวอย่างเช่นใช้การเข้ารหัสหมายเลขคริสตจักร ... เช่น หมายเลขคริสตจักรของค่าจำนวนเต็ม n แสดงโดยฟังก์ชันที่ใช้ฟังก์ชันกับค่า n ครั้ง คู่และค่าแลมบ์ดาเชิงลบมีความรู้สึกคล้าย ๆ กับพวกเขาหรือไม่?
zcaudate

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

@zcaudate [คำอธิบายประกอบ Type: 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กลับไม่ได้)
ไม่มีใคร

@zcaudate ฟังก์ชั่นพิเศษมีความจำเป็นเนื่องจากตัวเลขที่เข้ารหัสโดยคริสตจักร "เรียกคืนด้วยตนเอง" แต่คู่จะส่งส่วนประกอบให้คุณเท่านั้น ผู้ช่วยทำหน้าที่เพียงติดส่วนประกอบเข้าด้วยกันตามลำดับ "ถูกต้อง" (ซึ่งเกิดขึ้นโดยอัตโนมัติสำหรับ nats) ดูเพิ่มเติมที่: en.wikipedia.org/wiki/ ...... - การเข้ารหัสของโบสถ์นั้นมีfold . ctorไว้สำหรับผู้สร้างและประเภทนั้นfold( r) (ซึ่งเป็นสาเหตุสำหรับประเภทแบบเรียกซ้ำข้อมูลจะ "หักล้างด้วยตัวเอง" สำหรับประเภทที่ไม่เกิดซ้ำมันเหมือนกับการcaseจับคู่รูปแบบ / มากกว่า)
ไม่มีใคร

13

แลมบ์ดาแคลคูลัสสามารถเข้ารหัสโครงสร้างข้อมูลและประเภทพื้นฐานส่วนใหญ่ได้ ตัวอย่างเช่นคุณสามารถเข้ารหัสคู่ของคำศัพท์ที่มีอยู่ในแคลคูลัสแลมบ์ดาโดยใช้การเข้ารหัสของโบสถ์เดียวกับที่คุณมักจะเห็นเพื่อเข้ารหัสจำนวนเต็มและบูลีนที่ไม่จำเป็น:

FST = λพี P ( λ x Y . x ) snd = λพี p ( λ x y . y )

pair=λxyz.zxy
fst=λp.p(λxy.x)
snd=λp.p(λxy.y)

จากนั้นทั้งคู่คือP = ( จับคู่ )และถ้าคุณต้องการที่จะได้รับกลับและคุณสามารถทำ( FST  P )และ ( snd  P )(a,b)p=(pair ab)ab(fst p)(snd p)

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

(sign,n)

และตอนนี้คุณมีจำนวนเต็มสัมพัทธ์ การคูณนั้นง่ายต่อการกำหนดคุณแค่ต้องใช้ฟังก์ชันxorกับเครื่องหมายและการคูณจำนวนธรรมชาติบนค่าสัมบูรณ์:

mult=λab.pair  (xor(fst a)(fst b))  (mult(snd a)(snd b))

ในการกำหนดการเพิ่มคุณต้องเปรียบเทียบตัวเลขธรรมชาติสองตัวและใช้การลบเมื่อสัญญาณแตกต่างกันดังนั้นนี่ไม่ใช่คำศัพท์ แต่คุณสามารถปรับได้ถ้าคุณต้องการ:

add=λab.{(true,add(snd a)(snd b))if a0b0(false,add(snd a)(snd b))if a<0b<0(true,sub(snd a)(snd b))if a0b<0|a||b|(false,sub(snd b)(snd a))if a0b<0|a|<|b|(true,sub(snd b)(snd a))if a<0b0|a|<|b|(false,sub(snd a)(snd b))if a<0b0|a||b|

แต่การลบนั้นง่ายต่อการกำหนด:

ย่อย = λ เพิ่ม (a)(ลบ b)

minus=λa.pair(not(fst a))(snd a)
sub=λab.add(a)(minusb)

เมื่อคุณมีจำนวนเต็มบวกและเชิงลบที่คุณสามารถกำหนดเลขที่ซับซ้อนได้อย่างง่ายดายมาก: มันเป็นเพียงแค่คู่ของสองจำนวนเต็มซึ่งหมายถึง+ ฉัน นอกจากนี้การเติมจุดและการคูณเป็นปกติแต่ฉันจะไม่เขียนมันควรจะง่าย:(a,b)a+bi

add[i]=λz1z2.pair(add(fst z1)(fst z2))(add(snd z1)(snd z2))

6
k(a,b)k=ab

จำนวนเต็มคอมเพล็กซ์ก็ได้ แต่เขาถามหาจำนวนเชิงซ้อน จากนั้นอีกครั้งแน่นอนว่าพวกเขาไม่สามารถแสดงได้เนื่องจากมีนับไม่ได้
HdM

@ AndrejBauer: เคล็ดลับที่ดีมาก (อาจไม่ใช่เรื่องง่าย) HdM: แน่นอนว่าพวกเขาทำได้แม้จะไม่ใช่ทั้งหมดก็ตาม แต่ฉันคิดว่าวิธีการสร้างสิ่งของในแคลคูลัสด้วยการเข้ารหัสของคริสตจักรนั้นสำคัญกว่า / เหมาะสมกว่าที่นี่
jmad

ฉันหวังว่าฉันจะให้คำตอบที่ถูกต้องสองข้อ =) ฉันไม่ได้คิดว่าจะแสดง reals ได้เมื่อฉันถามถึงจำนวนเชิงซ้อน แต่คุณไป!
zcaudate
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.