Λ-अभिव्यक्तियों को SK-अभिव्यक्तियों में बदलें


20

Λ-पथरी , या लैम्ब्डा पथरी, एक तार्किक अनाम प्रक्रियाएं पर आधारित प्रणाली है। उदाहरण के लिए, यह एक λ-अभिव्यक्ति है:

λf.(λx.xx)(λx.f(xx))

हालाँकि, इस चुनौती के प्रयोजनों के लिए, हम इस अधिसूचना को सरल करेंगे:

  • बदलने के λलिए \(टाइप करने के लिए यह आसान बनाने के लिए):\f.(\x.xx)(\x.f(xx))
  • .लैम्ब्डा हेडर में, अनावश्यक है तो हम इसे छोड़ कर सकते हैं:\f(\xxx)(\xf(xx))
  • दो कार्यों को एक साथ लिखने के बजाय आवेदन के साथ अनलम्बास्टाइल -उपसर्ग उपसर्ग संकेतन का उपयोग करें `(यह कैसे करें की पूरी व्याख्या के लिए , लैंबडा कैलकुलस नोटिफ़िकेशन के बीच कनवर्ट देखें ):\f`\x`xx\x`f`xx
  • यह सबसे जटिल प्रतिस्थापन है। प्रत्येक चर को कोष्ठक में एक संख्या के साथ बदलें, इस आधार पर कि चर कितना गहरा घोंसला है, यह लैम्बडा हेडर के सापेक्ष है (जिसका उपयोग 0-आधारित डी ब्रूजन इंडेक्सिंग है )। उदाहरण के लिए, \xx(पहचान फ़ंक्शन) xमें, शरीर [0]में चर को बदल दिया जाएगा , क्योंकि यह पहले (0-आधारित) हेडर से संबंधित है, जब अभिव्यक्ति को चर से अंत तक ट्रेस किया जाता है; \x\y``\x`xxxyमें परिवर्तित हो जाएगा \x\y``\x`[0][0][1][0]। अब हम हेडर में चर छोड़ सकते हैं, छोड़कर \\``\`[0][0][1][0]

संयुक्त तर्क मूल रूप से एक ट्यूरिंग टारपिट है जो λ- पथरी से बना है (ठीक है, वास्तव में, यह पहले आया था, लेकिन यहां अप्रासंगिक है।)

"संयोजन तर्क को लैम्ब्डा कैलकुलस के एक प्रकार के रूप में देखा जा सकता है, जिसमें लैम्बडा एक्सप्रेशंस (कार्यात्मक अमूर्तता का प्रतिनिधित्व करते हैं) को कॉम्बिनेटरों के सीमित सेट द्वारा प्रतिस्थापित किया जाता है, आदिम फ़ंक्शंस जिसमें से बाध्य चर अनुपस्थित होते हैं।" 1

कॉम्बिनेटर लॉजिक का सबसे सामान्य प्रकार एसके कॉम्बिनेटर कैलकुलस है , जो निम्नलिखित प्राइमेटिव का उपयोग करता है:

K = λx.λy.x
S = λx.λy.λz.xz(yz)

कभी-कभी एक कॉम्बीनेटर I = λx.xजोड़ा जाता है, लेकिन यह निरर्थक है, जैसा SKK(या वास्तव SKxमें किसी के लिए x) के बराबर है I

आप सभी की जरूरत है कश्मीर, एस, और आवेदन λ-पथरी में किसी भी अभिव्यक्ति को एनकोड करने में सक्षम होने के लिए। एक उदाहरण के रूप में, यहाँ फ़ंक्शन λ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 स्रोत: विकिपीडिया

चुनौती

अब तक, आपने शायद अनुमान लगाया है कि क्या है: एक प्रोग्राम लिखें जो एक मान्य λ-अभिव्यक्ति लेता है (ऊपर वर्णित संकेतन में) इनपुट और आउटपुट (या रिटर्न) के रूप में एक ही फ़ंक्शन, SK-combinator पथरी में फिर से लिखा गया। ध्यान दें कि इसे फिर से लिखने के लिए अनंत तरीके हैं; आपको केवल अनंत तरीकों में से एक को आउटपुट करने की आवश्यकता है।

यह , इसलिए सबसे कम वैध जमा (बाइट्स में मापा गया) जीतता है।

परीक्षण के मामलों

प्रत्येक परीक्षण के मामले में एक संभव उत्पादन दिखाता है। शीर्ष पर अभिव्यक्ति बराबर λ-पथरी अभिव्यक्ति है।

λ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


1
मुझे लगता है कि आपका दूसरा परीक्षण मामला सही नहीं है। अंतिम में कोष्ठक में नहीं एक संख्या है।
क्रिश्चियन सेवर्स


आपको कैसे मिली λ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)सही के रूप में दर्शाया गया है ?
बारबराकर्क

@BarbaraKwarc राइट, मेरा मतलब था SII, नहीं SKK। वह एक ग़लती थी।
फल जूना

जवाबों:


9

हास्केल, 251 237 222 214 बाइट्स

15 बाइट्स ने @ _rjan_Johansen को धन्यवाद दिया (टिप्पणी में उनके TIO लिंक भी देखें)!

@Nimi की बदौलत 8 और बाइट्स बच गए!

data E=S|K|E:>E|V Int
p(h:s)|h>'_',(u,a)<-p s,(v,b)<-p u=(v,a:>b)|h>'['=a<$>p s|[(n,_:t)]<-reads s=(t,V n)
a(e:>f)=S:>a e:>a f
a(V 0)=S:>K:>K
a(V n)=K:>V(n-1)
a x=K:>x
o(e:>f)='`':o e++o f
o S="S"
o K="K"
f=o.snd.p

pइनपुट को पार्स करता है, परिणामस्वरूप जोड़ी के पहले घटक में शेष अप्रकाशित भाग को लौटाता है। इसके तर्क का पहला वर्ण बैकटिक, बैकस्लैश या ओपनिंग ब्रैकेट होना चाहिए। पैटर्न pइस क्रम में इन मामलों की जांच करता है। पहले मामले में, एक आवेदन को निरूपित करते हुए, दो और अभिव्यक्तियों को Einfixor के साथ डेटा प्रकार के एक तत्व में पार्स और संयोजित किया जाता है :>। लैम्ब्डा मामले में, निम्नलिखित अभिव्यक्ति को पार्स किया जाता है और तुरंत aफ़ंक्शन को दिया जाता है । अन्यथा यह एक चर है, हम readsफ़ंक्शन के साथ इसकी संख्या प्राप्त करते हैं (जो एक सूची लौटाता है) और पैटर्न से मेल खाते हुए समापन ब्रैकेट को छोड़ दें(_:t)

aसमारोह काफी अच्छी तरह से जाना जाता ब्रैकेट अमूर्त करता है। किसी एप्लिकेशन को अमूर्त करने के लिए, हम दो उप-विभाजनों का सार करते हैं और Sदोनों को तर्क वितर्क करने के लिए कॉम्बिनेटर का उपयोग करते हैं । यह हमेशा सही होता है, लेकिन अधिक कोड के साथ हम विशेष मामलों को संभालकर बेहतर कर सकते हैं ताकि छोटी अभिव्यक्तियों को प्राप्त किया जा सके। वर्तमान चर का सार देता है Iया, जब हमारे पास ऐसा नहीं है, तो SKK। आमतौर पर शेष मामले सिर्फ एक जोड़ सकते हैंK सामने वाले को , लेकिन इस अंकन का उपयोग करते समय हमें चरों को फिर से क्योंकि आंतरिक लैम्ब्डा सार है।

o आउटपुट के लिए स्ट्रिंग को परिणाम देता है। fपूरा कार्य है।

जैसा कि कई भाषाओं में, बैकस्लैश एक एस्केप कैरेक्टर है, इसलिए इसे दो बार स्ट्रिंग लिटरल में दिया जाना है:

*Main> f "\\[0]"
"``SKK"
*Main> f "\\`[0][0]"
"``S``SKK``SKK"
*Main> f "\\\\[0]"
"``S``S`KS`KK`KK"
*Main> f "\\\\[1]"
"``S`KK``SKK"
*Main> f "\\\\\\``[2][0]`[1][0]"
"``S``S`KS``S``S`KS``S`KK`KS``S``S`KS``S``S`KS``S`KK`KS``S``S`KS``S`KK`KK``S`KK``SKK``S``S`KS``S``S`KS``S`KK`KS``S`KK`KK``S`KK`KK``S``S`KS``S``S`KS``S`KK`KS``S``S`KS``S`KK`KK``S``S`KS`KK`KK``S``S`KS``S``S`KS``S`KK`KS``S`KK`KK``S`KK`KK"

1
1. दूसरी लाइन पर, आप उपयोग कर सकते हैं (a,(b,v))<-p<$>p s। 2. यदि आप उस मैच को अंतिम रूप से स्थानांतरित '\\'कर सकते हैं _
अर्जन जोहान्सन

1
दरअसल, पहले भाग को स्क्रैच करें: यह ट्यूपल ऑर्डर को स्वैप करने और p(_:s)=a<$>p s(स्थानांतरित) '\\'लाइन के लिए उपयोग करने के लिए छोटा है ।
अर्जन जोहानसन

1
इसे ऑनलाइन आज़माएं! अपने वर्तमान संस्करण के लिए। जिस तरह से केवल 236 बाइट्स हैं, आप अंतिम न्यूलाइन को छोड़ सकते हैं।
अर्जन जोहानसन

2
@ चैलेंजर 5 मुझे लगता है कि यह ज्यादातर इस तथ्य के कारण है कि हेकेल लैम्ब्डा कैलकुलस पर आधारित है, इसलिए हस्केल में प्रवीण लोगों को इस तरह के प्रश्नों के प्रति आकर्षित होने की अधिक संभावना है :)
लियो

2
आप परिभाषित कर सकते हैं p, तीन गार्ड के साथ एक एकल अभिव्यक्ति के साथ मामलों को पुनर्व्यवस्थित और की ज़रूरत से ज़्यादा जोड़ी ड्रॉप (): p(h:s)|h>'_',(u,a)<-p s,(v,b)<-p u=(v,a:>b)|h>'['=a<$>p s|[(n,_:t)]<-reads s=(t,V n)
nimi
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.