[functional] fixed-pointer operator 가 무엇인지 알아야 아래

임창진의 이미지

Lua 라는 언어를 공부하는 중인데 아래의 코드가 샘플로 들어있습니다.
factorial을 구하는 함수라는건 알겠는데 Y function이 도대체 뭘 하는놈인지 짐작도 못 하고 있습니다.
2틀동안 들여다 보면서
fixed point 라는게 수학용어이고
f(x) = x 가 되는 고정점 이 있다 뭐 이정도밖에 알아내지 못 했습니다. 근데 그 이론이랑 아래 코드랑 뭔 연관이 있는지 고수님들의 조언이 필요합니다.

-- function closures are powerful
-- traditional fixed-point operator from functional programming
Y = function (g)
      local a = function (f) return f(f) end
      return a(function (f)
                 return g(function (x)
                             local c=f(f)
                             return c(x)
                           end)
               end)
end

-- factorial without recursion
F = function (f)
      return function (n)
               if n == 0 then return 1
               else return n*f(n-1) end
             end
    end

factorial = Y(F)   -- factorial is the fixed point of F

-- now test it
function test(x)
	io.write(x,"! = ",factorial(x),"\n")
end

for n=0,16 do
	test(n)
end
[/b]
임창진의 이미지

http://en.wikipedia.org/wiki/Fixed_point_combinator

여기에 이렇게 나와있네요

Quote:
Y is a function with the property that f(Y(f)) = Y(f) for all functions f.

One well-known fixed point combinator, discovered by Haskell B. Curry, is

Y = λf.(λx.(f (x x)) λx.(f (x x)))

익명 사용자의 이미지

floating point : 부동소수점, 대충.. 실수
fixed point : 고정소수점 , 대충.. 정수

lifthrasiir의 이미지

사실 뭐 그냥 간단하게 생각해서 factorial 구하는 걸 꼬아 놓은 거죠 8) lua에서 함수를 변수처럼 다룰 수 있다는 걸 보이기 위해서 일부러 꼬아 놓은 것 같습니다. (웬만한 스크립트 언어는 다 그렇지만;)

Anonymous wrote:
floating point : 부동소수점, 대충.. 실수
fixed point : 고정소수점 , 대충.. 정수

안타깝게도 여기서 나오는 fixed point는 실수 표현과 별 관련이 없을 뿐 더러, 고정 소숫점으로 표현되는 실수는 정수가 절대로 아닙니다.

- 토끼군

차리서의 이미지

임창진 wrote:
Lua 라는 언어를 공부하는 중인데 아래의 코드가 샘플로 들어있습니다.
factorial을 구하는 함수라는건 알겠는데 Y function이 도대체 뭘 하는놈인지 짐작도 못 하고 있습니다.
2틀동안 들여다 보면서
fixed point 라는게 수학용어이고
f(x) = x 가 되는 고정점 이 있다 뭐 이정도밖에 알아내지 못 했습니다. 근데 그 이론이랑 아래 코드랑 뭔 연관이 있는지 고수님들의 조언이 필요합니다.
-- function closures are powerful
-- traditional fixed-point operator from functional programming
Y = function (g)
      local a = function (f) return f(f) end
      return a(function (f)
                 return g(function (x)
                             local c=f(f)
                             return c(x)
                           end)
               end)
end

-- factorial without recursion
F = function (f)
      return function (n)
               if n == 0 then return 1
               else return n*f(n-1) end
             end
    end

factorial = Y(F)   -- factorial is the fixed point of F

-- now test it
function test(x)
	io.write(x,"! = ",factorial(x),"\n")
end

for n=0,16 do
	test(n)
end

Lua를 전혀 몰라서 코드를 읽기가 몹시 우울하지만, 나머지 궁금해하시는 부분들에 대해서 최대한 간단하게 설명해보겠습니다. 코드의 의미와 연계시켜 이해하는 부분은 Lua를 잘 아시는 분께서 설명해주셔야할 것 같습니다.

코드에 나오는 Y function이란 combinatory logic의 Y combinator를 가리키는 것이로군요. Combinatory logic은 항상 λ-calculus를 따라다니는 이야기이므로 먼저 λ-calculus부터 설명하겠습니다. (λ-calculus는 그 자체만으로도 두꺼운 책 한 권을 쓸 수 있을만큼 깊고 관련 내용이 방대하지만, 지금은 다 필요 없습니다. 정확히 ‘기본’만, 그 중에서도 선택적으로 일부만 짚고 넘어가면 지금은 일단 충분하며, 아주 간단합니다!) 일단은 타입이 없는 untyped λ-calculus입니다:

  • λ-term
    • (변수) 모든 변수 v는 λ-term입니다.
    • (함수 합성) 모든 변수 v와 모든 λ-term M에 대해서, λv.M 은 λ-term입니다. (정확하고 좋은 예시는 아니지만 C 프로그래머에게 밑그림이 되어줄만한 설명을 덧붙이자면, λv.M 이란 일단 대략 type_of(M) f(v) { return M; }
      정도로 받아들이시면 되겠습니다.)
    • (함수 적용) 모든 λ-term M과 N에 대해서, (M N)은 λ-term입니다. (이는 결국 전통적인 표기법으로는 M(N)에 해당하며 (그래서 ‘함수 적용’입니다), 이런 표기법을 juxtapositioning이라고 합니다. λ-calculus 뿐만 아니라 Haskell, ML 등 이를 기반으로하는 함수형 프로그래밍 언어들도 juxtapositioning을 쓰고있습니다.)
  • 치환 규칙 (단, 자유변수와 종속변수에 대한 정확한 제한은 제외한 rough한 설명입니다)
    • (α-변환) λx.M은 λy.M[y/x] 와 같습니다. (단, M[y/x]란 M속에 자유변수로서 등장하는 모든 x들을 y로 싹 바꾼 결과입니다.) 역시 C 프로그래머용 설명을 덧붙이자면, 다음 두 개의 C 함수가 같은 계산을 의미하고 있음을 상기하시면 되겠습니다:
      int succ1(x) { return x + 1; }
      int succ2(y) { return y + 1; }

    • (β-치환) λv.M N은 M[N/v]이랑 같습니다. 역시 다음 C 함수 "호출"과 그 값을 계산하는 과정을 생각하시면 됩니다:
      succ1(5);
      5 + 1;

      즉, λv.M N을 M[N/v]으로 β-치환한다는 것은 결국 인수 N에 함수 λv.M을 적용한 (조금 더 C스러운 다른 말로는, 함수 λv.M을 인수 N을 주어 호출한) 결과를 ‘계산’하는 것입니다.
    • (η-치환) 어떤 두 람다 텀 M1과 M2가 있을 때, 만일 모든 람다 텀 N에 대해서 M1 N = M2 N이면 M1 = M2입니다. 이 부분은 사실은 자동 타입 추론 (inference, 타입 체킹과는 다릅니다!) 과정에서 심각한 이슈들을 양산하는 부분이긴하지만, 지금 이 글타래와 큰 상관은 없으니 생략합니다.
Untyped λ-calculus의 나머지 내용은 위와 같은 문법과 의미 정의로부터 출발하는 속성들이므로, 일단은 이 정도만 설명해도 지금 이 글타래에 대한 답변을 진행하는 데에는 충분하지않을까 생각합니다. Typed λ-calculus는 조금 더 재미있어지는데, 지금은 타입 이론까지 자세히 설명할 필요(그리고 시간)가 없을 뿐더러, 무엇보다도 Y combinator가 이슈가 되는 부분은 바로 이것이 untyped λ-calculus의 특징이기 때문이므로 일단 보류하겠습니다.

Combinator란 “함수부에 자유변수가 등장하지 않는 함수”입니다. 즉, 함수부가 오로지 인수들만으로 구성되는 함수라는 뜻입니다. 하지만, 일단은 그냥 위와 같은 람다 텀으로 만들 수 있는 일종의 ‘템플릿 함수’라고 받아들이시면 될 것 같습니다. 물론 Combinatory logic 자체도 일가를 이룬 재미있는 연구 분야이지만, Y combinator의 정체만 간단히 설명하는 데에는 다음과 같은 설명으로 충분할 것 같습니다:

일단, 유명한 SK(I) 시스템을 소개하겠습니다. (단, 앞으로는 불필요한 괄호는 생략합니다. 즉, 람다 텀의 적용은 왼쪽이 먼저 결합하므로 ((L M) N)은 그냥 L M N으로 쓰겠습니다. 또한, 관례적으로 combinator들은 로만체 대문자 볼드로 쓰지만, 이 문서에서는 지금까지처럼 그냥 대문자로 쓰는 것으로만 합니다) SK 시스템이란 말 그대로, S, K 두 개의 combinator들로만 (혹은 조금 사족스럽게 I combintor까지 세개로만) 이루어지는 시스템이고, 이들만 가지고도 대부분(전부 다는 아니고 이게 매우 아스트랄한 부분인데, 저도 당장은 정확히 설명할 수 없으므로 생략합니다. 잇힝~)의 계산을 기술할 수 있는 재미있는 시스템입니다. 각 combinator(즉, 함수)들의 정의는 다음과 같습니다 :

S x y z = x z (y z)
K x y   = x
I x     = x

이 정의가 혹시 juxtapositioning 때문에 헛갈리실까봐, combinatory logic의 관례에는 어긋나지만 (게다가 partial application도 불가능한 다른 타입이 되어버리지만) 편의를 위해 전통적인 표기법으로 다음과 같이 고쳐써보겠습니다:
S(x, y, z) = x(z, y(z))
K(x, y)    = x
I(x)       = x

그런데, 위 정의에 따라 ((S K K) x)를 계산하면 다음과 같습니다:
((S K K) x) = S K K x      -- combinator 적용의 결합 우선순위에 의함
            = K x (K x)    -- S의 정의에 의함
            = x            -- K의 정의에 의함

즉, ((S K K) x) = x입니다. 위에서 I x = x였으므로 결국 I x = (S K K) x가 되고, η-치환 규칙에 따라 (이 η-치환이라는게 좀 문제가 있을 때도 있지만 여기서는 괜찮으니 넘어갑시다) I = S K K입니다. 결론적으로, I의 정의는 위와 같이 따로 정의하는 대신 S와 K의 정의만 가지고도 파생시킬 수 있었다는 얘기입니다. 그래서 이 시스템을 SKI 시스템이라고 하지 않고 SK 시스템이라고 합니다. I와 마찬가지로, 심지어 자연수 체계 같은 대부분의 계산 대상과 함수들(실은 이들이 서로 다르지 않지만)을 오로지 S와 K만으로 나타낼 수 있다는 의미이기도 합니다.

제가 맨 처음에 λ-calculus 이야기를 왜 했냐하면, 사실은 위에 써놓은 S, K, I의 정의는 (λ-calculus의 기본에 비해 상대적으로) 매우 고차원적인 기법인 ‘패턴 매칭’을 이용해 정의한 것이고, 만일 패턴 매칭이 없다면 위에서처럼 정의할 수는 없습니다. λ-calculus의 기본만 가지고 정의하려면 다음과 같이 정의됩니다:

S = λx.(λy.(λz.(x z (y z)))) = λx.λy.λz.(x z (y z))
K = λx.(λy.x) = λx.λy.x
I = λx.x

여기까지는 서론이었고, 이제 본론으로 들어가기 전에 잠깐 (여흥 삼아) 이들 combinator들의 타입을 확인해봅시다. 타입에 대해서 자세히 설명하지는 않겠습니다. (어차피 나중에 Y의 타입을 자세히 들여다봐야하니 여기서는 맛보기만...!) 타입을 제가 그냥 막 써드릴 수도 있지만, 제가 실수할지도 모르니 Haskell 인터프리터의 힘을 잠시 빌려보겠습니다:

Hugs.Base> :type s    where   s x y z = x z (y z)
let {...} in s :: (a -> b -> c) -> (a -> b) -> a -> c
Hugs.Base> :type k    where   k x y = x
let {...} in k :: a -> b -> a
Hugs.Base> :type i    where   i x = x
let {...} in i :: a -> a
Hugs.Base>

이렇게 매우 정상적이고 상식적인 타입들이 나옵니다. (실토하자면, 사실 이 combinator들은 typed λ-calculus의 대표적인 combinator들이었습니다. Typed λ-calculus에서는 예를 들어 Y 같은 (의미상) 말도 안되는 combinator는 만들어질 수도 없고, 만들어져서도 안됩니다. 역사적으로는 오히려 거꾸로, Y 같은 (전통적인 계산학의 테두리 안에서 생각할 때) 허무맹랑한 combinator가 만들어질 수 없게끔 보증하기 위해서 λ-calculus에 type 개념이 추가된 것이라고 보셔도 됩니다.)

자, 그럼 이제 본론인 Y combinator를 보겠습니다. Untyped λ-calculus에 동반하는 combinatory logic에는 전통적으로 수많은 combinator들이 등장했었고 일일이 열거하기도 벅찰만큼 그 종류가 많습니다. 가장 두드러진 예로는 자연수 체계를 combinator로만 표현하는 예가 있으며, 유명한 Church numerals도 (넓은 의미에서는) 일종의 combinator로 볼 수 있습니다. 이 중에서 Y는 일종의 (그리고 가장 대표적인) fixed point combinator입니다. 이미 wikipedia에서 Y의 정의는 찾으셨군요.

토끼군님께서 이미 말씀하신 대로, fixed point란 고정소수점 수를 뜻하는게 아닙니다. 어떤 함수 f의 fixed point란 (혹은 문헌에 따라 줄여서 그냥 fixpoint라고도 하더군요) f(x) = x가 되는 x를 뜻합니다. 이걸 왜 fixed point라고 부르냐하면: ‘일반적’으로 함수는 x, f(x), f(f(x)), f(f(f(x))), ...이렇게 진행될 때마다 그 함수값이 계속 달라집니다만, 만일 어떤 p에 대해서 f(p) = p라면, 이때부터는 f(p), f(f(p)), f(f(f(p))), ... 이렇게 전개해도 더이상 값이 변하지 않고 고정(fix)되기 때문입니다. 자연수를 1 증가시키는 함수 succ을 예로 들면, 0, succ(0), succ(succ(0)), ...가 계속 바뀌다가 ω에 도달하면 더이상 바뀌지 않고 고정됩니다. (ω + 1 = ω) 그래서 succ의 fixpoint는 ω라고 이야기합니다.

λ-calculus로 합성할 수 있는 모든 함수에는 반드시 fixpoint가 있습니다. (Tarski 등을 검색해보셔요~) 이 의미는, 다시 말하자면, 어떤 함수 f를 인수로 주어도 그 함수 f의 fixpoint를 계산해내는 (그 계산 복잡도가 얼마든 간에) 함수 Y가 존재한다는 뜻입니다. 따라서 이런 Y는 반드시 λ-calculus로 만들어낼 수 있습니다. 이게 바로 임창진님께서 이미 찾아내신 표현식
Y = λf.(λx.(f (x x)) λx.(f (x x)))
입니다. 람다 텀으로 써놓으니까 뭔가 무시무시해보이는데, 패턴 매칭을 써서 재귀적으로 정의해도 된다면 다음과 같이 간단히 정의할 수 있게됩니다:
Y f = f (Y f)
(아마 MIT 전산과 홈페이지에 가보면 대문에 그려진 엠블렘에 위 식이 적혀있을겁니다.) 그런데, 눈치채셨을지도 모르지만, 이렇게 정의하면 combinator의 정의에 위배됩니다. Combinator란 분명히 그 함수부에 자유변수가 등장하지 않는다고 했었는데, 위 정의에 보면 Y라는 자유변수(정확한 번역은 아니지만, C 프로그래머가 이해하기 쉽게 약간 외곡해서 번역하자면 global variable)가 등장합니다. 그러니 이렇게 정의한 Y 함수는 함수이긴하되 combinator는 아니죠.

Y는 분명히 combinator이고, combinator답게 S와 K, I만으로 만들어낼 수 있습니다 (단, Untyped라고 가정했을 때에만!):
Y = S (K (S I I)) (S (S (K S) K) (K (S I I)))
(찾으신 wikipedia 문서에 보니 더 간단한 정의도 있군요. 실은 모르고 있었는데, 덕분에 저도 좋은거 하나 알았습니다. :) ) 그런데 이 정의가 과연 타입이 적용되어도 맞을까요? Haskell 인터프리터에게 물어보니:

Comb> :b
module Comb where
s :: (a -> b -> c) -> (a -> b) -> a -> c
k :: a -> b -> a
i :: a -> a
Comb> :type y where y = s (k (s i i)) (s (s (k s) k) (k (s i i)))
ERROR - Type error in application
*** Expression     : s i i
*** Term           : i
*** Type           : (a -> b) -> a -> b
*** Does not match : a -> a -> b
*** Because        : unification would give infinite type

Comb>

라는군요. 역시 안됩니다. 즉, Y라는 놈은 실제로는 ‘최소한 combinator로서는’ 타입이 맞지 않는 괴물딱지죠. 그런데 이런 Y를 일반 함수로는 (당연히) 정의할 수 있습니다. 위에 나왔던 식을 그대로 써보면:
Comb> :type y   where   y f = f (y f)
let {...} in y :: (a -> a) -> a
Comb>

이렇게 되는군요.

왜 Y가 fixed point를 찾아주는지는 위 식을 보시면 곧바로 유추해낼 수 있습니다. 예를 들어 succ이라는 함수를 Y의 인수로 주면:
Y succ = succ (Y succ) = succ (succ (Y succ)) = succ (succ (succ (Y succ)))
이런 식으로 계속 이어집니다. 즉, succ (succ (succ (succ (succ ...., 따라서 자연수의 크기, 즉 ω죠. 그러나, 물론 Y 함수의 의미가 그렇다는 뜻일 뿐이고, 실제로 이 값을 계산해내는건 완전히 다른 이야기입니다.

Comb> (+ 1) 3
4 :: Integer
Comb> y (+ 1) where y f = f (y f)

ERROR - Control stack overflow
Comb>

최대한 간단하게 설명하려고 했는데, 쓰다보니 결국 잡설이 길어져버렸군요. 결론적으로, Lua 코드에 나오는 Y의 정의는 제가 제대로 읽어낼 수 없지만, 아래에 나오는 F의 정의는 대충 읽을만하네요. F는 어떤 함수 f를 입력받아서 새로운 함수 하나를 리턴하는 함수인데, 이 새로운 함수는 자연수 n을 입력받아서 1 혹은 ‘f가 연계된’ 계산값 n * f(n-1)을 리턴합니다. 즉, 이 함수 F의 fixpoint가 곧 factorial 함수가 되는군요.

보너스로 타입을 잠시 추론해보면: F가 리턴하는 함수의 타입은 nat → nat이고, 이 함수의 함수부로부터 f의 타입도 역시 nat → nat이어야함을 알 수 있습니다. 따라서 F의 타입은 ((nat → nat) → (nat → nat))입니다. Y의 타입이 ∀a∈Type: (a → a) → a 이었으므로 이 경우에는 a에 nat → nat이 대응되어 결국 Y의 타입이 ((nat → nat) → (nat → nat)) → (nat → nat)인 셈이고, 따라서 Y(F), 즉 factorial의 타입은 nat → nat이 됩니다.

Y의 정의에서 함수부에 보면 "local"이 아마도 (좀더 널리 쓰이는 용어로) "let"인 모양인데, 그렇게 놓고 보아도 역시 코드가 좀 읽기에 난해하군요. 누군가 Lua를 아시는 분이 답해주시겠죠. 아무튼, 이 Y의 정의가 위에 설명한 Y combinator의 정의를 구현해놓은 것임은 분명합니다:

PS: Y combinator의 경우 (특히 타입 검증을 까다롭게 하는 언어일수록) 실제 계산은 매우 곤란한 문제인데, Lua의 경우에는 Y를 실제로 계산해낼 수 있다는 사실이 매우 흥미롭습니다. 혹은, 제가 결국 읽어내지 못한 저 Lua 코드가 실은 Y combinator의 원래 의미 그대로를 구현해둔 것이 아니라, fixed point에서 정말로 계산을 멈출 수 있게끔 Lua 나름대로의 꽁수를 써서 조금 왜곡해둔 코드인지도 모르죠. 아무튼, 조만간에 Lua를 한 번 제대로 보긴 봐야할 것 같습니다. :)

[/][/][/]

--
자본주의, 자유민주주의 사회에서는 결국 자유마저 돈으로 사야하나보다.
사줄테니 제발 팔기나 해다오. 아직 내가 "사겠다"고 말하는 동안에 말이다!

sliver의 이미지

차리서 wrote:

토끼군님께서 이미 말씀하신 대로, fixed point란 고정소수점 수를 뜻하는게 아닙니다. 어떤 함수 f의 fixed point란 (혹은 문헌에 따라 줄여서 그냥 fixpoint라고도 하더군요) f(x) = x가 되는 x를 뜻합니다. 이걸 왜 fixed point라고 부르냐하면: ‘일반적’으로 함수는 x, f(x), f(f(x)), f(f(f(x))), ...이렇게 진행될 때마다 그 함수값이 계속 달라집니다만, 만일 어떤 p에 대해서 f(p) = p라면, 이때부터는 f(p), f(f(p)), f(f(f(p))), ... 이렇게 전개해도 더이상 값이 변하지 않고 고정(fix)되기 때문입니다. 자연수를 1 증가시키는 함수 succ을 예로 들면, 0, succ(0), succ(succ(0)), ...가 계속 바뀌다가 ω에 도달하면 더이상 바뀌지 않고 고정됩니다. (ω + 1 = ω) 그래서 succ의 fixpoint는 ω라고 이야기합니다.

이 부분이 제 생각과 다르군요.
0, succ(0), succ(succ(0)), ... 이렇게 아무리 간다고 하더라도 결국 만들어 낼 수 있는 것은 succ^n(0) (where n은 유한한 자연수) 뿐입니다.
즉 ω에 도달 할 수 없습니다.
하지만 ω를 여전히 어떤 것의 fixpoint로 나타낼 수 있습니다:
ω = {0} U { succ(n) | n은 ω의 원소 } 라는 방정식으로부터
F(X) = {0} U { succ(n) | n은 X의 원소 }라는 함수를 이끌어내면
ω = F의 least fixpoint가 됩니다.
즉 succ^n(0) 이러한 형태들만을 모아놓은 집합입니다.
이렇게 보았을 때, ω + 1 = ω은 절대 사실이 아닙니다.
ω + 1의 의미는 ω란 집합의 모든 원소보다도 큰 원소 하나를 ω에 집어넣은 well-ordered 집합(또는 ordinal number)입니다.
즉 ω + 1 = ω U {T} where T > x for all x in ω.
하지만 아시다시피 ω에서는 가장 큰 원소라는 게 없습니다(ω의 원소 n이 가장 큰 원소라고 주장한다면 succ(n) 도 ω의 원소이므로 바로 모순입니다).
따라서 ω + 1 \= ω 입니다.
왠지 꼬투리 잡은 것 같은 느낌이 들기도 하지만 명확히 집고 넘어갔으면 좋겠다는 생각에 댓글을 답니다.

그리고 원글 쓰신분의 이해를 더 도와보자면:
차리서님께서 말씀하신 것 처럼 Y F = F (Y F) 입니다.
(더 정확히는 Y F는 F (Y F)로 convertible하다 인 것 같은데 확실히 모르겠네요)
이것이 어떻게 재귀함수의 계산에 쓰일 수 있을지 다들 잘 아시는 factorial의 예를 들어보겠습니다.
fact =λn. if n=0 then 1 else n * fact(n-1)
(if then else, true, false, 자연수 등등이 lambda calculus에서 인코딩될 수 있다는 것은 잘 알려진 사실이니 알아보기 쉽게 이렇게 나타내겠습니다)
fact는 자신의 정의안에 fact라는 자기 자신을 사용하였는데
대신에 자기 자신을 나타내는 함수를 인자로써 받도록 수정해 보면:
F = λf.λn.if n=0 then 1 else n * f(n-1) 가 됩니다.
이제 fact 2라는 값을 계산해 보면:
(Y F) 2 =
F (Y F) 2 = (F의 첫번째 인자 f에 Y F를 적용하면)
(λn.if n=0 then 1 else n * (Y F) (n-1) ) 2 = (n에 2를 적용하면)
if 2=0 then 0 else 2 * (Y F) (2-1) = (2=0은 false이므로)
2 * (Y F) (1) = ...
이런 식으로 계속 가게 되면 결국 (Y F) (1)의 계산은 결국 1*(Y F) (0)가 될 것이고 (Y F) (0)은 if n=0 then 1 부분에 의해 1으로 계산되게 되어서 결과는 2*1*1을 계산한 2가 됩니다.
위의 예에서 알 수 있듯이 combinator Y는 F의 첫번째 인자에 우리가 나타내고자 하는 재귀함수(Y F)를 넘겨준다고 생각하면 됩니다.

happibum의 이미지

임창진 wrote:
http://en.wikipedia.org/wiki/Fixed_point_combinator

여기에 이렇게 나와있네요

Quote:
Y is a function with the property that f(Y(f)) = Y(f) for all functions f.

One well-known fixed point combinator, discovered by Haskell B. Curry, is

Y = λf.(λx.(f (x x)) λx.(f (x x)))

괄호가 틀렸네요. 정확하게 쓰면,
Y = λf.(λx.f (x x)) (λx.f (x x))

그리고 Y combinator도 recursive type으로 타입을 입힐수 있습니다.
ocaml에서,

$ ocaml -rectypes

# let y f = (fun x -> f (x x)) (fun x -> f (x x));;
val y : ('a -> 'a) -> 'a = <fun>

ocaml이나 lisp처럼 eager evaluation을 하는 대부분의 언어들은 Y combinator를 쓰면 combinator 자체 계산에서 무한 loop에 빠집니다. 그래서 약간 다른 형태의 Y combinator를 이용합니다. 위의 lua 예제도 아래 Y'을 이용했습니다.

Y' = λf.(λg.λx.f (g g) x) (λg.λx.f (g g) x)

$ocaml -rectypes

# let y' f = (fun g -> fun x -> f (g g) x) (fun g -> fun x -> f (g g) x);;
val y' : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b = <fun>
# (y' (fun f -> fun n -> if n=0 then 1 else f (n-1) * n)) 5;;
- : int = 120;;

recursive type(mu-type)은 functional 쪽보다는 oo 쪽에서 더 중요합니다.(object의 self type) 그래서 ocaml(objective caml)은 지원하지만 haskell은 제낀듯하군요;;;

정정사항: Y combinator자체의 계산에서 무한루프에 빠지는 것이 아니라 Y f, 즉 함수의 fixed point를 구하는 과정에서 무한루프에 빠집니다.

차리서의 이미지

sliver wrote:
왠지 꼬투리 잡은 것 같은 느낌이 들기도 하지만 명확히 집고 넘어갔으면 좋겠다는 생각에 댓글을 답니다.

꼬투리라니요. 매우 중요한 지적을 하셨습니다. :)

sliver wrote:
0, succ(0), succ(succ(0)), ... 이렇게 아무리 간다고 하더라도 결국 만들어 낼 수 있는 것은 succ^n(0) (where n은 유한한 자연수) 뿐입니다.
즉 ω에 도달 할 수 없습니다.

일단, 이 말씀에는 전적으로 동의합니다. Fixpoint의 기본적인 의미만을 설명하는 데에 transfinite number에 대한 이야기까지는 불필요할 것 같아서 일부러 상당히 rough하게 설명을 했거든요. 말씀하신 대로, succ을 constructive하게는 계속 적용하는 것만으로는 결코 ω에 도달할 수 없는것이 사실입니다. 결국은 기껏해야 succ^n(0)이겠고, 어떤 succ^n(0)을 제시하더라도 succ^(n+1)(0)이 항상 존재하니 이는 ω가 아니죠. (그래서 나중에 “이 값을 실제로 계산해내는 것은 또다른 문제”라고 사족을 달아놓긴 했습니다만, 솔직히 말하자면 무의식중에 자세히 설명할 자신이 없어서 일종의 ‘빠져나가기’를 구사한건지도 모르겠습니다.)

sliver wrote:
하지만 ω를 여전히 어떤 것의 fixpoint로 나타낼 수 있습니다:
ω = {0} U { succ(n) | n은 ω의 원소 } 라는 방정식으로부터
F(X) = {0} U { succ(n) | n은 X의 원소 }라는 함수를 이끌어내면
ω = F의 least fixpoint가 됩니다.
즉 succ^n(0) 이러한 형태들만을 모아놓은 집합입니다.

다만, 쓰신 글을 읽다가 평소에 궁금했던 내용을 마침 여쭤볼 수 있는 기회일 것 같은 생각이 드는군요: ω = {0} ∪ { succ(n) | n ∈ ω } 라고 집합으로 기술하셨는데, 이 집합은 분명히 자연수의 집합 N 자체와는 다른 의미여야하지 않을까 싶어서 말입니다. 그래서 일단, sliver님께서 자연수의 집합과 ω를 어떻게 formalize하고계신지부터 제가 제대로 이해하고 있어야 그 뒤의 내용을 진행할 수 있을 것 같습니다. 일단 제가 sliver님 글을 이해한 바가 맞는지 확인해주셨으면합니다:

제 경우에는 ‘자연수’라는 집합 N을 생각할 때 (제 분야의 특성과 이로 인한 오랜 습관 때문에) 먼저 Church numerals부터 떠올려버리곤 하는데, 이렇게 Church numerals를 염두에 두고 위 ω의 식을 보니 자연수 집합의 정의 그 자체로 보였나봅니다. sliver님의 formalization은 아마도 보다 전통적인 집합론에서 자연수 집합을 기술하는 (특수 문자 중에 공집합 기호를 못 찾아서 phi로 대신합니다):

N = {φ, {φ}, {φ, {φ}}, {φ, {φ}, {φ, {φ}}}, ...}

이었던 것 같군요. 이렇게 생각하면 무슨 말씀을 하시는지 조금은 알 수 있을 것 같거든요. 즉, 이렇게 생각하면 일단 “각각의 자연수는 그 자체가 집합”이라는 사실을 아무런 거부감 없이 받아들일 수 있습니다. 예를 들어, 0 = φ, 1 = {φ}, 2 = {φ, {φ}}, ...하는 식이죠. 그리고 이렇게 정의된 자연수의 집합 N은 비록 집합이지만, 집합 간의 포함 관계 ⊆를 곧바로 이 집합의 원소들에 대한 well-order로 사용할 수 있으므로 (즉, {φ} ⊆ {φ, {φ}, {φ, {φ}}} 이므로 1 ⊆ 3 하는 식으로 ordering이 가능하며, well-ordering임), 이 order 관계에 따라 항상 정렬되어있다고 간주하고 모든 원소를 ‘몇 번 째 원소’라고 지칭하겠습니다.

자, 그러면 이제 이러한 자연수 집합 N의 n번째 원소(즉, n-1에 해당하는 자연수)는 간단히 ‘N의 n-1번째 원소까지를 모두 원소로 갖는 집합’이라고 말할 수 있게되었습니다. 그리고 이에 따르면 ω = φ ∪ { ω }가 되네요. (맞나요? 왠지 갑자기 R-set paradox가 떠오르는게 좀 불안한데요... 에구 -_-; ) 아무튼, 만일 여기까지가 맞다면, 이를 다시 (한 단계 initialization을 거친 후) combinatoric한 용어로 바꿔서 ω = {0} ∪ { succ(n) | n ∈ ω }라고 말씀하신 것까지는 이해가 됩니다.

그 다음 F 함수도 얼추 이렇게 이해했습니다: 일단 F는 자연수로부터 자연수로의 함수입니다. 위에서 집합론으로 자연수를 formalize해둔 바에 따라, 모든 자연수는 그보다 작은 모든 자연수들을 원소로 갖는 집합이므로 (예를 들어 4라는 자연수는 결국 {0, 1, 2, 3}이라는 집합이므로), X라는 자연수의 모든 원소들 각각의 다음번 자연수들과 0의 합집합을 만들면, 결국 X의 바로 다음번 자연수(러프하게 말해서 X+1)가 됩니다. 예를 들어, 3이라는 자연수는 자연수 집합의 정의 상 결국 {0, 1, 2}이므로,

F(3) = {0} ∪ { succ(n) | n ∈ 3 }
     = {0} ∪ { succ(n) | n ∈ {0, 1, 2} }
     = {0} ∪ {1, 2, 3}
     = {0, 1, 2, 3}
     = 4

이렇게 되는군요. 따라서 F란 successor 함수를 표현하신 것이라고 이해했습니다.

다만, 집합론적 자연수 기술에서 successor 함수 F를 정의하는 데에 있어서 combinatoric한 용어로서 succ을 또다시 쓰고 있다는 점은 조금 그렇군요. 순수하게 집합론적 자연수 기술로부터 successor를 만드는 것이었다면 F(X) = X ∪ {X} 정도라면 어땠을까 싶습니다만……. (단, 제가 아예 첫 단추부터 잘못 이해한 것이었다면 그저 낭패입니다. 긁적)

※ 혹시 지적하실지도 모르는 부분 한 가지에 대해서 제가 미리 부연해두겠습니다. Church numerals와 집합론적 자연수는 어찌보면 그다지 다른 점이 없어보일지도 모르겠지만, 타입이 깔끔하게 기술되는 전자와는 달리, 후자의 타입에는 몹시 곤란한 부분이 발생합니다. 간단히 예시를 하자면, 3∈N이고 5∈N인데 3∈5이기도 하게되거든요. 제가 평소에 전자를 먼저 떠올리고 선호하는 이유이기도 합니다. 집합은... (제 공력 부족 탓이겠지만서도) ... 역시 뭔가 이상해요. :(

sliver wrote:
이렇게 보았을 때, ω + 1 = ω은 절대 사실이 아닙니다.
ω + 1의 의미는 ω란 집합의 모든 원소보다도 큰 원소 하나를 ω에 집어넣은 well-ordered 집합(또는 ordinal number)입니다.
즉 ω + 1 = ω U {T} where T > x for all x in ω.
하지만 아시다시피 ω에서는 가장 큰 원소라는 게 없습니다(ω의 원소 n이 가장 큰 원소라고 주장한다면 succ(n) 도 ω의 원소이므로 바로 모순입니다).
따라서 ω + 1 \= ω 입니다.

질문의 본론은 이 부분입니다. 다만 질문을 드리기 전에, 일단 저도 (제가 저지른 실수에 대해서) 한 가지 정정을 해두겠습니다: 제가 쓰려던 식은 ω + 1 = ω이 아니라 1 + ω = ω이었습니다. 큰 실수를 저지르고 말았군요. :oops:

각설하고, ‘가장 큰 원소’라는게 least upper bound를 말씀하신 것인지 maxmial element를 말씀하신 것인지, greatest element를 말씀하신 것인지 자세히 설명해주십사 부탁드립니다. (제가 항상 헛갈리는 부분이라서 그럽니다.) 일단 각각에 대한 정의를 지금 제가 제대로 기억하고 있다면, ω에는 분명히 greatest element는 없지만 LUB는 있어야할 것 같습니다. 그리고 제 생각에는 그 LUB가 곧 ω 자체가 되는 것이라고 생각합니다만, 제가 뭘 잘못 생각하고 있을까요?

이 질문을 드리는 진짜 이유는, 실은 ω∈N인지ω\∈N인지를 알고싶어서입니다. 생각할 때마다 자꾸 다른 결론이 나와서 말이죠. :cry:

--
자본주의, 자유민주주의 사회에서는 결국 자유마저 돈으로 사야하나보다.
사줄테니 제발 팔기나 해다오. 아직 내가 "사겠다"고 말하는 동안에 말이다!

차리서의 이미지

happibum wrote:
그리고 Y combinator도 recursive type으로 타입을 입힐수 있습니다.
ocaml에서,
$ ocaml -rectypes

# let y f = (fun x -> f (x x)) (fun x -> f (x x));;
val y : ('a -> 'a) -> 'a = <fun>

ocaml이나 lisp처럼 eager evaluation을 하는 대부분의 언어들은 Y combinator를 쓰면 combinator 자체 계산에서 무한 loop에 빠집니다. 그래서 약간 다른 형태의 Y combinator를 이용합니다. 위의 lua 예제도 아래 Y'을 이용했습니다.

Y' = λf.(λg.λx.f (g g) x) (λg.λx.f (g g) x)

$ocaml -rectypes

# let y' f = (fun g -> fun x -> f (g g) x) (fun g -> fun x -> f (g g) x);;
val y' : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b = <fun>
# (y' (fun f -> fun n -> if n=0 then 1 else f (n-1) * n)) 5;;
- : int = 120;;

recursive type(mu-type)은 functional 쪽보다는 oo 쪽에서 더 중요합니다.(object의 self type) 그래서 ocaml(objective caml)은 지원하지만 haskell은 제낀듯하군요;;;

헉! 역시 변형된 Y였군요.

그나저나 (아무리 자주 손대지는 않는다고 해도) 저도 Ocaml을 계속 보고 있다고 생각하고 있었는데, 제일 중요한 포인트 하나를 이렇게 놓치고 있었군요. 이런 중요한 사실을 오늘에야 처음 알게되었다니, 충격입니다. OTL

답변 달러 들어왔다가 오히려 제가 많이 배우고 갑니다. :)

--
자본주의, 자유민주주의 사회에서는 결국 자유마저 돈으로 사야하나보다.
사줄테니 제발 팔기나 해다오. 아직 내가 "사겠다"고 말하는 동안에 말이다!

무우의 이미지

[functional]이라는 태그가 나오고 관심을 가지신 분이 많은 것같습니다.
혹시 Joy라는 프로그래밍 언어에 대해서 한마디 해주실 분 안 계십니까?
S K 라는 문자도 낮이 읶고 해서.. 저는 문외한 입니다..

http://www.latrobe.edu.au/philosophy/phimvt/joy.html

sliver의 이미지

차리서 wrote:

sliver wrote:
하지만 ω를 여전히 어떤 것의 fixpoint로 나타낼 수 있습니다:
ω = {0} U { succ(n) | n은 ω의 원소 } 라는 방정식으로부터
F(X) = {0} U { succ(n) | n은 X의 원소 }라는 함수를 이끌어내면
ω = F의 least fixpoint가 됩니다.
즉 succ^n(0) 이러한 형태들만을 모아놓은 집합입니다.

다만, 쓰신 글을 읽다가 평소에 궁금했던 내용을 마침 여쭤볼 수 있는 기회일 것 같은 생각이 드는군요: ω = {0} ∪ { succ(n) | n ∈ ω } 라고 집합으로 기술하셨는데, 이 집합은 분명히 자연수의 집합 N 자체와는 다른 의미여야하지 않을까 싶어서 말입니다. 그래서 일단, sliver님께서 자연수의 집합과 ω를 어떻게 formalize하고계신지부터 제가 제대로 이해하고 있어야 그 뒤의 내용을 진행할 수 있을 것 같습니다. 일단 제가 sliver님 글을 이해한 바가 맞는지 확인해주셨으면합니다:

ω과 자연수의 집합 N과 달라야 하는 이유를 알 수 있을까요?
일단 이 부분을 제가 작성할 때 제가 생각했던 바를 말씀드리자면
ω는 peano axiom을 만족하는 집합이고 따라서 그것을 만족하도록 ω = {0} U { succ(n) | n은 ω의 원소 }를 만족하는 최소크기의 집합으로 정의를 한 것입니다.
즉 이 부분에서는 저는 단지 ω를 peano axiom을 만족하는 집합으로 보았습니다.

여기서부터는 아래 말씀하신대로 ω가 전통적인 집합론에서 말하는 것으로 생각하겠습니다.

차리서 wrote:

제 경우에는 ‘자연수’라는 집합 N을 생각할 때 (제 분야의 특성과 이로 인한 오랜 습관 때문에) 먼저 Church numerals부터 떠올려버리곤 하는데, 이렇게 Church numerals를 염두에 두고 위 ω의 식을 보니 자연수 집합의 정의 그 자체로 보였나봅니다. sliver님의 formalization은 아마도 보다 전통적인 집합론에서 자연수 집합을 기술하는 (특수 문자 중에 공집합 기호를 못 찾아서 phi로 대신합니다):

N = {φ, {φ}, {φ, {φ}}, {φ, {φ}, {φ, {φ}}}, ...}

이었던 것 같군요. 이렇게 생각하면 무슨 말씀을 하시는지 조금은 알 수 있을 것 같거든요. 즉, 이렇게 생각하면 일단 “각각의 자연수는 그 자체가 집합”이라는 사실을 아무런 거부감 없이 받아들일 수 있습니다. 예를 들어, 0 = φ, 1 = {φ}, 2 = {φ, {φ}}, ...하는 식이죠. 그리고 이렇게 정의된 자연수의 집합 N은 비록 집합이지만, 집합 간의 포함 관계 ⊆를 곧바로 이 집합의 원소들에 대한 well-order로 사용할 수 있으므로 (즉, {φ} ⊆ {φ, {φ}, {φ, {φ}}} 이므로 1 ⊆ 3 하는 식으로 ordering이 가능하며, well-ordering임), 이 order 관계에 따라 항상 정렬되어있다고 간주하고 모든 원소를 ‘몇 번 째 원소’라고 지칭하겠습니다.

자, 그러면 이제 이러한 자연수 집합 N의 n번째 원소(즉, n-1에 해당하는 자연수)는 간단히 ‘N의 n-1번째 원소까지를 모두 원소로 갖는 집합’이라고 말할 수 있게되었습니다. 그리고 이에 따르면 ω = φ ∪ { ω }가 되네요. (맞나요? 왠지 갑자기 R-set paradox가 떠오르는게 좀 불안한데요... 에구 -_-; ) 아무튼, 만일 여기까지가 맞다면, 이를 다시 (한 단계 initialization을 거친 후) combinatoric한 용어로 바꿔서 ω = {0} ∪ { succ(n) | n ∈ ω }라고 말씀하신 것까지는 이해가 됩니다.


어떻게 ω = φ ∪ { ω }이란 식을 얻으셨는지 궁금합니다.
아마도 자연수들의 집합인 ω 자체를 하나의 수라고 볼 때(즉 ordinal),
ω가 limit ordinal임을 생각하지 않으신 것 같습니다(즉, "ω는 어떤 수의 successor도 아니다"라는 것)

차리서 wrote:

그 다음 F 함수도 얼추 이렇게 이해했습니다: 일단 F는 자연수로부터 자연수로의 함수입니다. 위에서 집합론으로 자연수를 formalize해둔 바에 따라, 모든 자연수는 그보다 작은 모든 자연수들을 원소로 갖는 집합이므로 (예를 들어 4라는 자연수는 결국 {0, 1, 2, 3}이라는 집합이므로), X라는 자연수의 모든 원소들 각각의 다음번 자연수들과 0의 합집합을 만들면, 결국 X의 바로 다음번 자연수(러프하게 말해서 X+1)가 됩니다. 예를 들어, 3이라는 자연수는 자연수 집합의 정의 상 결국 {0, 1, 2}이므로,
F(3) = {0} ∪ { succ(n) | n ∈ 3 }
     = {0} ∪ { succ(n) | n ∈ {0, 1, 2} }
     = {0} ∪ {1, 2, 3}
     = {0, 1, 2, 3}
     = 4

이렇게 되는군요. 따라서 F란 successor 함수를 표현하신 것이라고 이해했습니다.

다만, 집합론적 자연수 기술에서 successor 함수 F를 정의하는 데에 있어서 combinatoric한 용어로서 succ을 또다시 쓰고 있다는 점은 조금 그렇군요. 순수하게 집합론적 자연수 기술로부터 successor를 만드는 것이었다면 F(X) = X ∪ {X} 정도라면 어땠을까 싶습니다만……. (단, 제가 아예 첫 단추부터 잘못 이해한 것이었다면 그저 낭패입니다. 긁적)


사실 저는 그런 의도로 F를 정의하지 않았는데도 이렇게도 해석이 가능하네요(신기하네요 :))
저는 단지 자연수의 집합 ω가 어떤 함수의 fixpoint로 정의(표현) 가능하다는 것을 보여주고 싶었을 뿐입니다.
위에서와 같이 "X+1 = X U {X}이다"라는 집합론적 자연수의 정의를 전혀 가정하지 않고
자연수의 집합 ω는 ω = {0} ∪ { succ(n) | n ∈ ω }를 만족하는 최소의 집합이라는 것으로부터
마치 이 쓰레드의 원래 주제인 :) 재귀함수를 Y combinator를 이용한 비재귀함수로 바꾸는 것과 비슷한 테크닉으로
오른쪽 term에 나타나는 ω를 어떤 인자 X로 치환시켜서 얻은 것입니다.
즉 F = \X. {0} ∪ { succ(n) | n ∈ X }
그런 후에 마치 저 위의 쓰레드 글에서와 같이 fact = Y F (여기서 F = \f.\n.if n=0 then 1 else n*f(n-1)) 인 것과 비슷하게
ω = least fixpoint of F (여기서 F = \X. {0} ∪ { succ(n) | n ∈ X } )를 얻은 것입니다.
F(φ) = {0}
F({0}) = {0, succ(0)}
F({0,succ(0)}) = {0, succ(0), succ(succ(0)) }
.....
F(ω) = ω

즉 제가 F를 정의할 때의 의도는 F의 정의에서 보이는 그대로
어떤 자연수들의 집합 X를 받아들여서 0과 X의 각 자연수들의 successor들의 집합을 반환해 주는
특별한 의미가 없는 함수로 정의하였습니다.

차리서 wrote:

sliver wrote:
이렇게 보았을 때, ω + 1 = ω은 절대 사실이 아닙니다.
ω + 1의 의미는 ω란 집합의 모든 원소보다도 큰 원소 하나를 ω에 집어넣은 well-ordered 집합(또는 ordinal number)입니다.
즉 ω + 1 = ω U {T} where T > x for all x in ω.
하지만 아시다시피 ω에서는 가장 큰 원소라는 게 없습니다(ω의 원소 n이 가장 큰 원소라고 주장한다면 succ(n) 도 ω의 원소이므로 바로 모순입니다).
따라서 ω + 1 \= ω 입니다.

질문의 본론은 이 부분입니다. 다만 질문을 드리기 전에, 일단 저도 (제가 저지른 실수에 대해서) 한 가지 정정을 해두겠습니다: 제가 쓰려던 식은 ω + 1 = ω이 아니라 1 + ω = ω이었습니다. 큰 실수를 저지르고 말았군요. :oops:

각설하고, ‘가장 큰 원소’라는게 least upper bound를 말씀하신 것인지 maxmial element를 말씀하신 것인지, greatest element를 말씀하신 것인지 자세히 설명해주십사 부탁드립니다. (제가 항상 헛갈리는 부분이라서 그럽니다.) 일단 각각에 대한 정의를 지금 제가 제대로 기억하고 있다면, ω에는 분명히 greatest element는 없지만 LUB는 있어야할 것 같습니다. 그리고 제 생각에는 그 LUB가 곧 ω 자체가 되는 것이라고 생각합니다만, 제가 뭘 잘못 생각하고 있을까요?


네.. 잘못 생각하고 계시는 것 같습니다.
일단 제가 말한 '가장 큰 원소'는 greatest element를 말한 것입니다.
ω가 LUB는 있어야 할 것 같다고 하셨는데 물론 유한한 집합에 대해서는 LUB가 존재합니다.
예를 들면 {1,4,5,7}과 같은 집합의 LUB는 7이 되겠지요.
하지만 짝수집합과 같은 무한한 집합에 대해서는 LUB가 존재하지 않습니다.
LUB가 ω가 되지 않느냐고 하셨는데 그렇지 않습니다.
LUB라는 것은 여전히 그 원소자체도 우리가 대상으로 하고 있는 집합에 속해야 하기 때문입니다.
즉 차리서님의 말씀대로라면 ω∈ω가 되어버리는 것입니다.
그런데 이것은 사실이 아니죠.

차리서 wrote:

이 질문을 드리는 진짜 이유는, 실은 ω∈N인지ω\∈N인지를 알고싶어서입니다. 생각할 때마다 자꾸 다른 결론이 나와서 말이죠. :cry:

ω와 N 모두 자연수들의 집합을 의미하기 때문에 서로 같은 것으로 생각하겠습니다.
결론은 ω\∈ω 입니다.
자연수들의 집합인 ω 자체가 자연수가 아니라는 사실을 생각하시면 됩니다.
왜 ω자체가 자연수가 아닌지는 ω가 어떤 자연수의 successor도 아니라는 사실로부터 입니다(즉 limit ordinal).
(자연수이려면 0이거나 혹은 어떤 자연수의 successor이어야 합니다)
차리서의 이미지

sliver wrote:
ω과 자연수의 집합 N과 달라야 하는 이유를 알 수 있을까요?

제가 ω라고 쓰면서도 계속 생뚱맞게 א-null이 머리속에 맴돌았기 때문입니다. :cry:

어쨌든 그래서,

차리서 wrote:
제 경우에는 ‘자연수’라는 집합 N을 생각할 때 (제 분야의 특성과 이로 인한 오랜 습관 때문에) 먼저 Church numerals부터 떠올려버리곤 하는데, 이렇게 Church numerals를 염두에 두고 위 ω의 식을 보니 자연수 집합의 정의 그 자체로 보였나봅니다.

이게 원래 지극히 당연했던거였군요. OTL

sliver wrote:
어떻게 ω = φ ∪ { ω }이란 식을 얻으셨는지 궁금합니다.
아마도 자연수들의 집합인 ω 자체를 하나의 수라고 볼 때(즉 ordinal),
ω가 limit ordinal임을 생각하지 않으신 것 같습니다(즉, "ω는 어떤 수의 successor도 아니다"라는 것)

제가 애초에 만들고 싶었던 nullary 함수 ω는 아래 Haskell 코드에 나오는 nats와 같은 것이었습니다:
module NatOnSet (
        NList (NNull, NCons), nmap, nats
) where

data NList      = NNull | NCons NList NList

instance Show NList where
        show n  = "{" ++ show' n ++ "}" where
                show' NNull             = ""
                show' (NCons h NNull)   = show h
                show' (NCons h t)       = show h ++ ", " ++ show' t

nmap f []       = NNull
nmap f (h:t)    = NCons (f h) (nmap f t)

nats = nmap nat [0..] where
        nat 0   = NNull
        nat n   = nmap nat [0 .. (n-1)]

그런데, 위 식 ω = φ ∪ {ω}를 쓰던 당시에는 위에서처럼 실제로 구현해보지 않았었고, 지금 코드를 작성하면서 다시 확인해보니 ω = φ ∪ {ω}로는 택도 없네요. 실제로 전개해보면
ω = φ ∪ {ω}
   = φ ∪ {φ ∪ {ω}}
   = φ ∪ {φ ∪ {φ ∪ {φ ∪ {ω}}}}
   = ...

혹은 더 간단히
ω = {ω}
   = {{ω}}
   = {{{ω}}}
   = ...

로 되어 완전히 어불성설이로군요. :? 털썩~ OTL 이런 제 헛소리들로 인해 혹시 시간을 뺏기셨다면 진심으로 사과드립니다.

sliver wrote:
하지만 짝수집합과 같은 무한한 집합에 대해서는 LUB가 존재하지 않습니다.
LUB가 ω가 되지 않느냐고 하셨는데 그렇지 않습니다.
LUB라는 것은 여전히 그 원소자체도 우리가 대상으로 하고 있는 집합에 속해야 하기 때문입니다.
즉 차리서님의 말씀대로라면 ω∈ω가 되어버리는 것입니다.
그런데 이것은 사실이 아니죠.

저도 지금부터 다시 책을 찾아서 읽어보겠습니다만, 위 밑줄친 부분이 항상 사실인가요? (제가 알고있던 것과는 다르군요. LUB는 대상 집합에 속할 수도 있고 속하지 않을 수도 있는 것으로 알고있었습니다.) 만일 사실이라면 저는 아예 order theory를 처음부터 다시 공부해야할 지경이로군요. :cry:

sliver wrote:
결론은 ω\∈ω 입니다.
자연수들의 집합인 ω 자체가 자연수가 아니라는 사실을 생각하시면 됩니다.
왜 ω자체가 자연수가 아닌지는 ω가 어떤 자연수의 successor도 아니라는 사실로부터 입니다(즉 limit ordinal).
(자연수이려면 0이거나 혹은 어떤 자연수의 successor이어야 합니다)

좋은 말씀 감사드립니다. 하지만 애석하게도, 지금 이 상태로 논의를 더 이어나가기에는 아무래도 제가 잘못 알고있는 사실들이 너무 많아서 sliver님의 시간만 괜시리 빼앗게될 것 같습니다. 다시 처음부터 차근차근 찾아 읽고 새로 공부한 후에 (그래도 역시 이상하면 그 때) 여쭤보도록 하겠습니다.

마지막으로 딱 한 가지만 더 여쭙자면, 지금까지 이야기된 자연수의 formalization에 따르면
3∈ω ∧ 5∈ω ∧ 3∈5
가 성립한다는 사실을 어떻게 받아들이고 계신지요? 아무 문제가 없는건가요?

--
자본주의, 자유민주주의 사회에서는 결국 자유마저 돈으로 사야하나보다.
사줄테니 제발 팔기나 해다오. 아직 내가 "사겠다"고 말하는 동안에 말이다!

notpig의 이미지

차리서 wrote:

sliver wrote:
하지만 짝수집합과 같은 무한한 집합에 대해서는 LUB가 존재하지 않습니다.
LUB가 ω가 되지 않느냐고 하셨는데 그렇지 않습니다.
LUB라는 것은 여전히 그 원소자체도 우리가 대상으로 하고 있는 집합에 속해야 하기 때문입니다.
즉 차리서님의 말씀대로라면 ω∈ω가 되어버리는 것입니다.
그런데 이것은 사실이 아니죠.

저도 지금부터 다시 책을 찾아서 읽어보겠습니다만, 위 밑줄친 부분이 항상 사실인가요? (제가 알고있던 것과는 다르군요. LUB는 대상 집합에 속할 수도 있고 속하지 않을 수도 있는 것으로 알고있었습니다.) 만일 사실이라면 저는 아예 order theory를 처음부터 다시 공부해야할 지경이로군요. :cry:

잠시 안들어오고 있는 사이에 이런 주제가 이야기 되고 있었네요
아직 다 읽어보질 못해서 잘 모르지만.

LUB 가 제가 아는 Least Upper Bound 라면 대상 집합에 항상 속해 있어야 합니다. 제가본 정의에선 대상 집합에 속해 있게 정의가 되어 있습니다.

Types and Programming Langage 17 page wrote:

s and t are elements of S.
an element j in S is said to be a least Upper bound of s and t if
.....

다시 보니 대상 집합을 s,t 라고 보면 속해있지 않아도 되는군요~
여기서 대상 집합의 정의가 어떻게 되는거죠??

sliver의 이미지

차리서 wrote:

sliver wrote:
어떻게 ω = φ ∪ { ω }이란 식을 얻으셨는지 궁금합니다.
아마도 자연수들의 집합인 ω 자체를 하나의 수라고 볼 때(즉 ordinal),
ω가 limit ordinal임을 생각하지 않으신 것 같습니다(즉, "ω는 어떤 수의 successor도 아니다"라는 것)

제가 애초에 만들고 싶었던 nullary 함수 ω는 아래 Haskell 코드에 나오는 nats와 같은 것이었습니다:
module NatOnSet (
        NList (NNull, NCons), nmap, nats
) where

data NList      = NNull | NCons NList NList

instance Show NList where
        show n  = "{" ++ show' n ++ "}" where
                show' NNull             = ""
                show' (NCons h NNull)   = show h
                show' (NCons h t)       = show h ++ ", " ++ show' t

nmap f []       = NNull
nmap f (h:t)    = NCons (f h) (nmap f t)

nats = nmap nat [0..] where
        nat 0   = NNull
        nat n   = nmap nat [0 .. (n-1)]

그런데, 위 식 ω = φ ∪ {ω}를 쓰던 당시에는 위에서처럼 실제로 구현해보지 않았었고, 지금 코드를 작성하면서 다시 확인해보니 ω = φ ∪ {ω}로는 택도 없네요. 실제로 전개해보면
ω = φ ∪ {ω}
   = φ ∪ {φ ∪ {ω}}
   = φ ∪ {φ ∪ {φ ∪ {φ ∪ {ω}}}}
   = ...

혹은 더 간단히
ω = {ω}
   = {{ω}}
   = {{{ω}}}
   = ...

로 되어 완전히 어불성설이로군요. :? 털썩~ OTL 이런 제 헛소리들로 인해 혹시 시간을 뺏기셨다면 진심으로 사과드립니다.

헛..아닙니다 ;)

차리서 wrote:

sliver wrote:
하지만 짝수집합과 같은 무한한 집합에 대해서는 LUB가 존재하지 않습니다.
LUB가 ω가 되지 않느냐고 하셨는데 그렇지 않습니다.
LUB라는 것은 여전히 그 원소자체도 우리가 대상으로 하고 있는 집합에 속해야 하기 때문입니다.
즉 차리서님의 말씀대로라면 ω∈ω가 되어버리는 것입니다.
그런데 이것은 사실이 아니죠.

저도 지금부터 다시 책을 찾아서 읽어보겠습니다만, 위 밑줄친 부분이 항상 사실인가요? (제가 알고있던 것과는 다르군요. LUB는 대상 집합에 속할 수도 있고 속하지 않을 수도 있는 것으로 알고있었습니다.) 만일 사실이라면 저는 아예 order theory를 처음부터 다시 공부해야할 지경이로군요. :cry:

제 말이 애매했을지도 모르니 한 번 정리해보겠습니다:
먼저 partially ordered set (P,≤)이 있다고 합시다.
P의 임의의 subset X⊆P의 upper bound는 다음과 같은 조건을 만족하는 원소입니다:
y is an upper bound of X if and only if y∈P and for all z∈X : z≤y.
즉, y가 X의 upper bound가 되려면 y는 어쨌든 먼저 전체 partial order P의 원소이어야 합니다.
그리고 least upper bound는:
y is the least upper bound of X if and only if y is an upper bound of X and for all z∈P : (if z is an upper bound of X then y≤z)

차리서 wrote:

마지막으로 딱 한 가지만 더 여쭙자면, 지금까지 이야기된 자연수의 formalization에 따르면
3∈ω ∧ 5∈ω ∧ 3∈5
가 성립한다는 사실을 어떻게 받아들이고 계신지요? 아무 문제가 없는건가요?

이상하다고 생각해 본 적은 없습니다.
앞의 두개의 ∈관계는 "ω는 모든 자연수의 집합"이라는 것 때문에 나온 것이고,
3번째의 ∈관계는 단지 "집합론에서 constructive하게 만들어낸 자연수의 특징 때문에 생겨난 관계일 뿐"이라고 생각합니다.
임창진의 이미지

wikipedia에서 읽어보고 이런게 있구나 했었느데... 차리서님을 비롯해서 여러고수님들이 친절하게 가르쳐주셔서 감사합니다.
덕분에 훨씬 잘 이해 할 수 있었습니다.

ps : lua를 계속해서 공부하고 있는중인데요 이게 제가 일하고있는데선(직장에선 java를 씁니다) 별로 사용일이 없는 언어입니다만. scite 라는 editor 에 lua 로 스크립트를 짜넣을수 있습니다. 그래서 배우게 되었는데 이게 language 그 자체로 매우 재미있습니다. 요즘 유행하는 언어인 python 이나 ruby 처럼 procedural + functional 의 성격을 가지고 있고요(이런걸 멀티 패러다임언어라고 하는거 같습니다) 거기에 meta table 라는걸 통해서 metaprogramming 비슷한걸 할수있게 만들어져 있습니다. 게임개발쪽에서는 이미 script 언어로 많이 쓰이고 있다고 합니다.

ps2 : 예전에 제가 haskell 공부하다 monad 에서 막혔었는데요 그거 쉽게 설명한 자료나 문서가 혹시 있을까요?

차리서의 이미지

임창진 wrote:
ps2 : 예전에 제가 haskell 공부하다 monad 에서 막혔었는데요 그거 쉽게 설명한 자료나 문서가 혹시 있을까요?

그러지 않아도 마침 요 며칠 새에 Haskell 메일링 리스트에 monad 입문서를 찾는다는 문의가 올라왔고, 그 답변 중에 다음 링크가 있었습니다:

http://www.nomaware.com/monads/html/index.html

저도 아직 읽어보지는 않았지만, 메일링 리스트에 원래 질문했던 사람은 매우 만족스러워하는 감사 인사를 남기더군요. 저도 조만간 한 번 읽어볼 생각입니다. :)

--
자본주의, 자유민주주의 사회에서는 결국 자유마저 돈으로 사야하나보다.
사줄테니 제발 팔기나 해다오. 아직 내가 "사겠다"고 말하는 동안에 말이다!

임창진의 이미지

차리서님 매번 답변주셔서 감사합니다.
:)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.