람다 미적분을 사용하여 음수와 복소수를 나타냄


답변:


18

먼저 jmad가 설명한대로 자연수와 쌍을 인코딩하십시오.

정수 표현 자연수의 쌍 ( , B ) 이되도록 K = - B를 . 그런 다음 정수에 대한 일반적인 연산을 다음과 같이 정의 할 수 있습니다 ( λ -calculus에 Haskell 표기법 사용 ).k(a,b)k=abλ

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 비율로 수렴하는 일련의 합리적 순서로 인코딩됩니다 .xfkNfkq|xq|<2kk2k

실수를 인코딩하는 것은 많은 작업이며 실제로 미적분학 에서는 원하지 않습니다 . 그러나 순수한 Haskell에서 실수를 간단히 구현하려면 Marshall 의 하위 디렉토리를 참조하십시오 . 이것은 원칙적으로 순수한 λ- 미적분 으로 변환 될 수 있습니다 .λetc/haskellλ


1
와우 =) 나는 그것이 의미하는 바를 직관적으로 궁금합니다. 예를 들어 교회 번호 인코딩을 사용하는 것입니다. 정수 값 n의 교회 수는 n 값에 함수를 적용하는 함수로 표현된다. 쌍과 음의 람다 값에 대해 비슷한 직관적 느낌이 있습니까?
zcaudate

1
교회 인코딩은 자연수 , 1 , 2 , ...를 인코딩합니다. 음수는 인코딩하지 않습니다. 위의 답변에서 나는 자연수의 인코딩에 대해 이미 알고 있다고 가정 했으므로 정수를 얻는 방법을 설명했습니다. 내가 인코딩 한 정수는 교회 숫자와 달리보다 공식적인 구조이며 λ- 미적분 과 더 복잡하게 연결됩니다 . "부정적인 람다 값"이 의미있는 문구라고 생각하지 않습니다. 012λ
Andrej Bauer 2016 년

@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. || 는 되돌릴 수 없습니다).
아무도

@zcaudate 추가 기능은 교회에서 인코딩 한 숫자가 "자주 재귀"되므로 필요하지만 쌍은 구성 요소 만 전달합니다. 도우미 함수는 구성 요소를 "올바른"순서로 붙입니다 (nats에 대해 자동으로 수행됨). 참조 : en.wikipedia.org/wiki/… – 교회 인코딩은 기본적 fold . ctor으로 모든 생성자 및 해당 유형 fold( r)에 적용됩니다. (재귀 유형의 경우 데이터가 "자체로 재귀"되는 이유는 무엇입니까? 비 재귀 유형의 경우 case/ 패턴 일치 와 비슷합니다 .)
nobody

13

람다 미적분은 대부분의 데이터 구조와 기본 유형을 인코딩 할 수 있습니다. 예를 들어, 음이 아닌 정수와 부울을 인코딩 하는 것과 동일한 교회 인코딩 을 사용하여 람다 미적분학에서 기존 용어 인코딩 할 수 있습니다 .

fst = λ p . p ( λ x y . x ) snd = λ p . p ( λ x y . y )

pair=λxyz.zxy
fst=λp.p(λxy.x)
snd=λp.p(λxy.y)

그런 다음 페어 p = ( pair  a b ) 이며 ab 를 되 찾으려면 ( fst  p )( snd  p )를 수행 할 수 있습니다 .(a,b)p=(pair ab)ab(fst p)(snd p)

즉, 왼쪽의 부호와 오른쪽의 절대 값 쌍으로 양수와 음수를 쉽게 표현할 수 있습니다. 부호는 숫자가 양수인지 여부를 지정하는 부울입니다. 오른쪽은 교회 인코딩을 사용하는 자연수입니다.

(sign,n)

이제 상대 정수가 생겼습니다. 곱셈을 쉽게 정의 할 수 있습니다. xor 만 적용하면됩니다.xor 함수 를 부호에 자연수에 대한 곱셈을 절대 값에 적용하면됩니다.

mult=λab.pair  (xor(fst a)(fst b))  (mult(snd a)(snd b))

더하기를 정의하려면 두 개의 자연수를 비교하고 부호가 다를 때 빼기를 사용해야하므로 이것은 λ 항이 아니지만 실제로 원하는 경우이를 조정할 수 있습니다.

add=λab.{(true,add(snd a)(snd b))if a0b0(false,add(snd a)(snd b))if a<0b<0(true,sub(snd a)(snd b))if a0b<0|a||b|(false,sub(snd b)(snd a))if a0b<0|a|<|b|(true,sub(snd b)(snd a))if a<0b0|a|<|b|(false,sub(snd a)(snd b))if a<0b0|a||b|

그러나 빼기는 정의하기가 정말 쉽습니다.

minus=λa.pair(not(fst a))(snd a)
sub=λab.add(a)(minusb)

양의 정수와 음의 정수가 있으면 복잡한 정수를 매우 쉽게 정의 할 수 있습니다. 두 정수의 쌍일뿐입니다.(,) 어느 것을 나타내는 +나는. 그런 다음 덧셈은 포인트 방식이며 곱셈은 평소 와 같지만 쓰지 않을 것입니다.

더하다[나는]=λ12.(더하다(fst 1)(fst 2))(더하다(snd 1)(snd 2))

6
대신 정수를 나타내는 경우 대소 문자 구분을 피할 수 있습니다 케이 한 쌍의 자연수 (,) 그런 케이=.
Andrej Bauer 2018 년

복잡한 정수는 괜찮지 만 복잡한 숫자를 요구했습니다. 다시 말하지만, 셀 수없는 것이기 때문에 그것들을 표현할 수는 없습니다.
HdM

@AndrejBauer : 아주 좋은 트릭 (아마 더 간단하지는 않을 수도 있음) HdM : 모든 것이 아니라도 가능합니다. 그러나 교회 인코딩으로 λ- 미적분으로 물건을 만드는 방법이 더 중요하고 적절하다고 생각했습니다.
jmad

나는 두 개의 정답을 줄 수 있기를 바랍니다 =) 나는 복잡한 숫자에 대해 물었을 때 실수가 표현 될 수 있다고 생각하지 않았지만 거기에 있습니다.
zcaudate
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.