λ式をSK式に変換


20

λ計算、又はラムダ計算は、匿名関数に基づいて、論理システムです。たとえば、これはλ式です。

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

ただし、この課題のために、表記を簡略化します。

  • に変更λします\(入力しやすくするため):\f.(\x.xx)(\x.f(xx))
  • .我々はそれをドロップすることができますので、ラムダヘッダーのは、不要です。\f(\xxx)(\xf(xx))
  • 使用Unlambdaとスタイルのプレフィックス表記を`(これを行う方法の完全な説明については、参照ではなく2つの関数を書くよりもアプリケーションのためのラムダ計算表記間の変換を):\f`\x`xx\x`f`xx
  • これは最も複雑な代替です。各変数を、その変数が属するラムダヘッダーに対してどれだけ深くネストされているかに基づいて、括弧内の数字で置き換えます(つまり、0ベースのDe Bruijnインデックスを使用します)。たとえば、\xx(恒等関数)では、式を変数から最後までトラバースするときに遭遇する最初の(0から始まる)ヘッダーに属するためx、本文のはに置き換えられ[0]ます。\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出典:ウィキペディア

チャレンジ

今までに、あなたはおそらく何であるかを推測しました:有効なλ式(上記の表記法)を入力および出力(または返す)としてSKコンビネーター計算で書き直されたプログラムを書く。これを書き換える方法は無限にあることに注意してください。無限の方法のいずれかを出力するだけです。

これはであるため、最短の有効な送信(バイト単位で測定)が優先されます。

テストケース

各テストケースは、1つの可能な出力を示します。上の式は、同等のλ計算式です。

λ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
2番目のテストケースは正しくないと思います。最後には、括弧内にない数字が含まれています。
クリスチャンシーバーズ


どうやって手に入れたのλ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

Haskell、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これらのケースをこの順序でチェックします。アプリケーションを示す最初のケースでは、さらに2つの式が解析されE、infix constructorを使用してデータ型の要素に結合され:>ます。ラムダの場合、次の式が解析され、すぐにa関数に渡されます。それ以外の場合は変数であるため、reads関数(リストを返す)でその番号を取得し、とのパターンマッチングによって閉じ括弧を削除し(_:t)ます。

このa関数は、よく知られているブラケット抽象化を行います。アプリケーションを抽象化するには、2つの部分式を抽象化し、Sコンビネーターを使用して両方に引数を配布します。これは常に正しいことですが、コードが多くなると、より短い式を取得するために特殊なケースを処理することで、より良い結果を得ることができます。現在の変数を抽象化すると、Iまたは、それがない場合はSKK。通常、残りの場合はa Kを先頭に追加するだけですが、この表記を使用する場合は、内側のラムダが抽象化されるため、変数の番号を付け直す必要があります。

o結果を出力用の文字列に変換します。f完全な機能です。

多くの言語と同様に、バックスラッシュはエスケープ文字であるため、文字列リテラルで2回指定する必要があります。

*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. 2行目では、を使用できます(a,(b,v))<-p<$>p s。2. '\\'ちょうどすることができ_ますが、最後にその試合を移動した場合。
Ørjanヨハンセン

1
実際には、最初の部分をスクラッチします。タプルの順序を入れ替えp(_:s)=a<$>p sて(移動した)'\\'行に使用する方が短いです。
Ørjanヨハンセン

1
オンラインでお試しください!現在のバージョン用。ちなみにこれはたった236バイトですが、最後の改行を削除できます。
Ørjanヨハンセン

2
@ Challenger5それは主にhaskellがラムダ計算に基づいているという事実によると思うので、haskellに習熟している人はこの種の質問に惹かれる可能性が高いです:)
レオ

2
あなたは定義することができp、3つのガードを持つ単一の式でケースを並べ替えるとの余分なペアをドロップ()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.