ラムダ計算を使用した負数と複素数の表現


回答:


18

jmadの説明に従って、最初に自然数とペアをエンコードします。

整数を、ような自然数ペアとして表します。次に、整数の通常の操作を次のように定義できます( -calculusのHaskell表記を使用):(、B )K = - bはλk(a,b)k=a−bλ

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. 有理数をペアとしてエンコードします。ここで、は整数、は自然、です。(k 、a )k a q = k /(1 + a )q(k,a)kaq=k/(1+a)
  2. すべての自然な、がような有理数エンコードするように、関数によって実数エンコードします 。つまり、実数は、レートで収束する有理数のシーケンスとしてエンコードされます。F のk ∈ N F k個のQ | x − q | < 2 - K K ↦ 2 - Kバツfk∈Nfkq|バツ−q|<2−kk↦2−k

実数のエンコードは大変な作業であり、 -calculus で実際に行うのは望ましくありません。しかし、純粋なHaskellでの実数の簡単な実装については、例えばMarshallのサブディレクトリを参照してください。これは原則として、純粋な -calculusに変換できます。λetc/haskellλ


1
うわー=)私は直感的にそれが何を意味するのか疑問に思っています...例えば、教会番号のエンコーディングを使用して...すなわち。整数値nの教会番号は、値にn回関数を適用する関数によって表されます。ペアと負のラムダ値は、それらについて同様の直感的な感覚を持っていますか?
— -zcaudate

1
教会はエンコードに自然数エンコード、、、...それは負の数をコードしません。上記の答えでは、自然数のエンコードについてすでに知っていると仮定したため、整数を取得する方法を説明しました。私がエンコードした整数は、 -calculus とより複雑に関連しているチャーチの数字とは異なり、より形式的な構造です。「負のラムダ値」は意味のあるフレーズだとは思いません。1 2 λ012λ
— アンドレイバウアー

@zcaudate [タイプ注釈: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は可逆です)。
— 誰も14

@zcaudate教会でエンコードされた数字は「独自に再帰する」ため、追加の関数が必要ですが、ペアはそのコンポーネントのみを渡します。ヘルパー関数は、単に「右」の順序で一緒に部品を接着も参照してください(NATのために自動的に起きている。):en.wikipedia.org/wiki/... -教会のエンコーディングは基本的にfold . ctor任意のコンストラクタのために、そのタイプのfold(r)。(これが、再帰型の場合、データが「それ自体で再帰する」理由です。非再帰型の場合は、case/パターンマッチに似ています。)
— 誰も14

13

ラムダ計算は、ほとんどのデータ構造と基本型をエンコードできます。たとえば、非負の整数とブール値をエンコードするために通常表示されるのと同じ教会エンコードを使用して、ラムダ計算の既存の用語のペアをエンコードできます。

、FST = λ P 。P (λ X 、Y 。X )SND = λ P 。P (λ X 、Y 。Y )

ペア=λバツyz。zバツy
fst=λp。p(λバツy。バツ)
snd=λp。p(λバツy。y)

次にペアあるとあなたが戻って取得したい場合やあなたが行うことができますと 。p = (ペア  a b )a b (fst  p )(snd  p )(a、b)p=(ペア ab)ab(fst p)(snd p)

これは、正と負の整数をペアで簡単に表すことができることを意味します:左側の符号と右側の絶対値。符号は、数値が正かどうかを指定するブール値です。権利は、教会のエンコードを使用した自然数です。

(s私gn、n)

そして今、あなたは相対的な整数を持っている。乗算の定義は簡単です。符号に関数を適用し、絶対値に自然数の乗算を適用するだけです。XOR

マルチℤ=λab。ペア  (XOR(fst a)(fst b))  (マルチℕ(snd a)(snd b))

加算を定義するには、2つの自然数を比較し、符号が異なるときに減算を使用する必要があるため、これはλ項ではありませんが、本当に必要な場合は調整できます。

追加ℤ=λab。{(本当、追加ℕ(snd a)(snd b))もし a≥0∧b≥0(偽、追加ℕ(snd a)(snd b))もし a<0∧b<0(本当、サブℕ(snd a)(snd b))もし a≥0∧b<0∧|a|≥|b|(偽、サブℕ(snd b)(snd a))もし a≥0∧b<0∧|a|<|b|(本当、サブℕ(snd b)(snd a))もし a<0∧b≥0∧|a|<|b|(偽、サブℕ(snd a)(snd b))もし a<0∧b≥0∧|a|≥|b|

しかし、減算は本当に簡単に定義できます:

マイナスℤ=λa。ペア(じゃない(fst a))(snd a)
サブℤ=λab。追加ℤ(a)(マイナスℤb)

正と負の整数が得られたら、複雑な整数を非常に簡単に定義できますを表すの 2つの整数ペアです。その後、加算はポイント単位で、乗算は通常どおりですが、私はそれを書かないでしょう、それは簡単なはずです:(a、b)a+b私

追加ℤ[私]=λz1z2。ペア(追加ℤ(fst z1)(fst z2))(追加ℤ(snd z1)(snd z2))

6
代わりに、ような自然数のペアとして整数を表す場合、大文字と小文字の区別を避けることができます。(a 、b )k = a − bk(a、b)k=a−b
— アンドレイバウアー

複素数の整数は大丈夫ですが、彼は複素数を求めていました。繰り返しになりますが、数え切れないほど存在するので、もちろんそれらを表すことはできません。
— HdM

@AndrejBauer:非常に素晴らしいトリック(たぶんそれほど単純ではないかもしれません)HdM:全部ではないにしても、できることは確かです。しかし、ここでは、チャーチエンコーディングを使用してλ計算でデータを作成する方法がより重要/適切であると考えました。
— -jmad

2つの正しい答えを出せたらいいのにと思います=)複素数について尋ねたとき、実数を表すことができるとは考えていませんでしたが、そこに行きます!
— -zcaudate
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.