λ- 표현식을 SK- 표현식으로 변환


20

λ 미적분 또는 람다 계산법 익명 함수에 기초하여 논리 시스템이다. 예를 들어, 이것은 λ- 표현식입니다 :

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

그러나이 과제의 목적을 위해 다음과 같은 표기법을 단순화합니다.

  • 변경 λ하려면 \(쉽게 입력 할 수 있도록하기 위해) :\f.(\x.xx)(\x.f(xx))
  • .우리가 그것을 놓을 수 있도록 람다 헤더는, 불필요 :\f(\xxx)(\xf(xx))
  • 두 함수를 함께 작성하는 대신 Unlambda 스타일 접두사 표기법 `을 응용 프로그램에 사용하십시오 (이 작업을 수행하는 방법에 대한 자세한 설명은 Lambda 미적분 표기법 사이 변환 참조 ).\f`\x`xx\x`f`xx
  • 이것은 가장 복잡한 대체입니다. 각 변수를 변수가 속한 람다 헤더에 얼마나 깊이 중첩되어 있는지에 따라 괄호 안의 숫자로 바꿉니다 (예 : 0 기반 De Bruijn 인덱싱 사용 ). 예를 들어, \xx(identity 함수)에서 xin [0]은 변수에서 끝으로 표현식을 탐색 할 때 발생하는 첫 번째 (0 기반) 헤더에 속하기 때문에 body로 대체됩니다 . \x\y``\x`xxxy로 변환됩니다 \x\y``\x`[0][0][1][0]. 이제 헤더에 변수를 삭제하고을 남겨 둘 수 \\``\`[0][0][1][0]있습니다.

조합 논리는 기본적으로 λ- 미적분으로 만들어진 튜링 타르 핏입니다 (실제로 먼저 나왔지만 여기서는 관련이 없습니다).

"조합 논리는 람다 미적분의 변형으로 볼 수 있는데, 여기서 람다 식 (기능적 추상화를 나타냄)은 한정된 결합 자 (결합 된 변수가없는 원시 함수)로 대체됩니다."1

가장 일반적인 유형의 조합 논리는 다음과 같은 기본 요소를 사용하는 SK 결합기 미적분입니다 .

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

때로는 콤비는 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

도전

지금까지는 무엇인지 짐작 하셨을 것입니다 : 위에서 설명한 표기법으로 유효한 λ- 표현식을 SK 컴비 네이터 미적분학으로 다시 작성된 동일한 함수로 입력 및 출력 (또는 리턴)하는 프로그램을 작성하십시오. 이것을 다시 작성하는 방법에는 무한한 방법이 있습니다. 무한한 방법 중 하나만 출력하면됩니다.

이것은 이므로 가장 짧은 유효한 제출 (바이트 단위로 측정)이 이깁니다.

테스트 사례

각 테스트 사례는 하나의 가능한 출력을 보여줍니다. 맨 위에있는 표현식은 동등한 λ- 미적분 표현식입니다.

λ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
두 번째 테스트 사례가 올바르지 않다고 생각합니다. 마지막은 괄호 안에없는 숫자를 포함합니다.
Christian Sievers


어떻게 얻었 λ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

@BarbaraKwarc 오른쪽, 나는 의미 SII하지 SKK. 그건 실수 였어
Esolanging 과일

답변:


9

하스켈, 251237222214 바이트

@ Ørjan_Johansen 덕분에 15 바이트가 절약되었습니다 (비고에서 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이러한 순서를 순서대로 점검합니다. 첫 번째 경우, 애플리케이션을 나타내는 두 개의 표현식이 구문 분석되고 Einfix 생성자를 사용하여 데이터 유형 의 요소에 결합됩니다 :>. 람다의 경우 다음 표현식이 구문 분석되어 즉시 a함수에 제공됩니다. 그렇지 않으면 변수이며 reads함수를 사용하여 번호를 얻습니다 (목록을 반환합니다) (_:t).

a함수는 잘 알려진 대괄호 추상화를 수행합니다. 애플리케이션을 추상화하기 위해 두 개의 하위 표현식을 추상화하고 S결합자를 사용 하여 인수를 둘 다에 분배합니다. 이것은 항상 정확하지만 코드가 많을수록 더 짧은 표현식을 얻기 위해 특수한 경우를 처리하여 훨씬 더 잘 수행 할 수 있습니다. 현재 변수를 추상화하면 I또는 그렇지 않은 경우 SKK. 일반적으로 나머지 경우는 K앞에 a 를 추가 할 수 있지만이 표기법을 사용할 때 내부 람다가 추상화 될 때 변수의 번호를 다시 매겨 야합니다.

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. 당신이 마지막으로 그 일치를 이동하는 경우 '\\'가 될 수 있습니다 _.
Ørjan Johansen 2014 년

1
실제로 첫 번째 부분을 긁으십시오. 튜플 순서를 바꾸고 p(_:s)=a<$>p s(이동 한) '\\'줄에 사용 하는 것이 더 짧습니다 .
Ørjan Johansen 2014 년

1
온라인으로 사용해보십시오! 현재 버전 그건 그렇고 236 바이트에 불과하므로 최종 줄 바꿈을 삭제할 수 있습니다.
Ørjan Johansen 5

2
@ Challenger5 하스켈이 람다 미적분학을 기반으로한다는 사실에 기인한다고 생각합니다. 따라서 하스켈에 능숙한 사람들은 이런 종류의 질문에 더 끌릴 것입니다 :)
Leo

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.