λแคลคูลัสหรือแลมบ์ดาแคลคูลัสเป็นระบบตรรกะขึ้นอยู่กับฟังก์ชั่นที่ไม่ระบุชื่อ ตัวอย่างเช่นนี่เป็นนิพจน์::
λf.(λx.xx)(λx.f(xx))
อย่างไรก็ตามสำหรับจุดประสงค์ของการท้าทายนี้เราจะทำให้สัญลักษณ์ง่ายขึ้น:
- เปลี่ยน
λ
เป็น\
(เพื่อให้พิมพ์ง่ายขึ้น):\f.(\x.xx)(\x.f(xx))
.
ในส่วนหัวของแลมบ์ดาไม่จำเป็นเพื่อให้เราสามารถวาง:\f(\xxx)(\xf(xx))
- ใช้Unlambdaสไตล์คำนำหน้าโน้ตด้วย
`
สำหรับการประยุกต์ใช้มากกว่าการเขียนทั้งสองฟังก์ชั่นด้วยกัน (สำหรับคำอธิบายเต็มรูปแบบของวิธีการทำเช่นนี้ดูแปลงระหว่างแลมบ์ดาแคลคูลัสสัญลักษณ์ ):\f`\x`xx\x`f`xx
- นี่เป็นการทดแทนที่ซับซ้อนที่สุด แทนที่ตัวแปรแต่ละตัวด้วยตัวเลขในวงเล็บตามความลึกของตัวแปรที่สัมพันธ์กับส่วนหัวแลมบ์ดาที่เป็นของมัน (เช่นใช้การทำดัชนี De Bruijn ที่ใช้ 0 ) ตัวอย่างเช่นใน
\xx
(ฟังก์ชั่นเอกลักษณ์),x
ในร่างกายจะถูกแทนที่ด้วย[0]
เพราะมันเป็นของส่วนหัว (ตามพื้นฐาน 0) พบเมื่อสำรวจภายในการแสดงออกจากตัวแปรไปยังจุดสิ้นสุด; จะถูกแปลงเป็น\x\y``\x`xxxy
ตอนนี้เราสามารถวางตัวแปรในส่วนหัวออก\x\y``\x`[0][0][1][0]
\\``\`[0][0][1][0]
ตรรกะเชิงผสมนั้นเป็นทัวริงทาร์พิทที่ทำจากcalcul-แคลคูลัส (จริง ๆ แล้วมันมาก่อน แต่มันไม่เกี่ยวข้องเลย)
"Combinatory ตรรกศาสตร์สามารถถูกมองว่าเป็นตัวแปรของแลมบ์ดาแคลคูลัสซึ่งแลมบ์ดานิพจน์ (แทนการทำหน้าที่เป็นนามธรรม) จะถูกแทนที่ด้วยชุด จำกัด combinators ฟังก์ชั่นดั้งเดิมที่ไม่มีขอบเขต จำกัด ตัวแปร" 1
ตรรกะที่พบได้บ่อยที่สุดคือแคลคูลัสของSK combinatorซึ่งใช้หลักการพื้นฐานต่อไปนี้:
K = λx.λy.x
S = λx.λy.λz.xz(yz)
บางครั้ง Combinator I = λx.x
คือเพิ่ม แต่มันจะซ้ำซ้อนเช่นSKK
(หรือแน่นอนSKx
สำหรับการใด ๆx
) I
เทียบเท่ากับ
สิ่งที่คุณต้องมีคือ K, S และแอปพลิเคชันเพื่อให้สามารถเข้ารหัสนิพจน์ใด ๆ ในλ-แคลคูลัส ดังตัวอย่างต่อไปนี้เป็นคำแปลจากฟังก์ชั่นλf.(λx.xx)(λx.f(xx))
เป็นตรรกะเชิงการรวม:
λf.(λx.xx)(λx.f(xx)) = S(K(λx.xx))(λf.λx.f(xx))
λx.f(xx) = S(Kf)(S(SKK)(SKK))
λf.λx.f(xx) = λf.S(Kf)(S(SKK)(SKK))
λf.S(Sf)(S(SKK)(SKK)) = S(λf.S(Sf))(K(S(SKK)(SKK)))
λf.S(Sf) = S(KS)S
λf.λx.f(xx) = S(S(KS)S)(K(S(SKK)(SKK)))
λx.xx = S(SKK)(SKK)
λf.(λx.xx)(λx.f(xx)) = S(K(S(SKK)(SKK)))(S(S(KS)S)(K(S(SKK)(SKK))))
```S`K``S``SKK``SKK``S``S`KSS`K``SKK`
เนื่องจากเรามีการใช้คำนำหน้าเอกสารนี้เป็น
1ที่มา: Wikipedia
ความท้าทาย
ถึงตอนนี้คุณอาจเดาได้ว่าคืออะไร: เขียนโปรแกรมที่ใช้ expression-expression ที่ถูกต้อง (ในสัญลักษณ์ที่อธิบายด้านบน) เป็นอินพุตและเอาต์พุต (หรือส่งคืน) ฟังก์ชันเดียวกันเขียนใหม่ในแคลคูลัส SK-combinator โปรดทราบว่ามีวิธีการเขียนนี้จำนวนอนันต์ คุณต้องการส่งออกหนึ่งในวิธีที่ไม่มีที่สิ้นสุด
นี่คือรหัสกอล์ฟดังนั้นการส่งที่ถูกต้องที่สั้นที่สุด (วัดเป็นไบต์) ชนะ
กรณีทดสอบ
แต่ละกรณีทดสอบแสดงผลลัพธ์ที่เป็นไปได้หนึ่งรายการ นิพจน์ด้านบนเป็นนิพจน์ calcul-แคลคูลัสที่เทียบเท่า
λx.x:
\[0] -> ``SKK
λx.xx:
\`[0][0] -> ```SKK``SKK
λx.λy.y:
\\[0] -> `SK
λx.λy.x:
\\[1] -> K
λx.λy.λz.xz(yz):
\\\``[2][0]`[1][0] -> S
λw.w(λx.λy.λz.xz(yz))(λx.λy.x):
\``[0]\\[1]\\\``[2][0]`[1][0] -> ``S``SI`KS`KK
λx.f(xx) = S(Kf)(SKK)
อย่างไร มันไม่ควรจะเป็นอย่างนั้นλx.f(xx) = S(Kf)(SII) = S(Kf)(S(SKK)(SKK))
หรือ เมื่อแปลงλx.f(xx)
ฉันจะได้รับS {λx.f} {λx.xx}
สิ่งที่ลดลงS (Kf) {λx.xx}
และการแสดงออกในวงเล็บไม่ได้เป็นอย่างอื่นω=λx.xx
ที่เรารู้ว่ามันแสดงออกSII = S(SKK)(SKK)
มาใช่ไหม?
SII
SKK
นั่นเป็นความผิดพลาด