Ailrun (UTC-5/-4)

@ailrun@hackers.pub · 3 following · 41 followers

소개 - Who Am I?

  • 개발자/연구원
  • Haskell Language Server Admin
  • PL Theorist
  • Logician
  • 중증 맥덕

근황 - Recent Interests

  • 언어간 상호운용성(Interoperability) 연구 중
  • 의존적 형이론(dependent type theory) 연구 중
  • 효율적인 레이텍 조판(LaTeX Typesetting) 공부 중
  • Québec 에서 제일 맛있는 Stout 마시는 중
GitHub Page
ailrun.github.io/ko
GitHub
@Ailrun
2

Hackers' Pub의 문제는 아니고 Firefox랑 Linux 한글 입력기랑 JS기반 입력기의 환장의 콜라보같은데, 긴 글을 치다보면 한글 입력을 가끔 씹는다. 이를테면 "우주로 가자."고 치는데 "우주로 가." 같이 쳐지는 상황\ldots 써진 걸 확인하면 될 일이지만 약간 "Zone"에 들어가서 정신없이 치다가 한 서너줄 전에 글자 하나 빠진 거 발견하면 아주 돌아버린다\ldots

0

Hackers' Pub의 문제는 아니고 Firefox랑 Linux 한글 입력기랑 JS기반 입력기의 환장의 콜라보같은데, 긴 글을 치다보면 한글 입력을 가끔 씹는다. 이를테면 "우주로 가자."고 치는데 "우주로 가." 같이 쳐지는 상황\ldots 써진 걸 확인하면 될 일이지만 약간 "Zone"에 들어가서 정신없이 치다가 한 서너줄 전에 글자 하나 빠진 거 발견하면 아주 돌아버린다\ldots

2

함수형을 공부하기 전, 함수 작업?의 대상을 {함수, 인자}로만 인식했었는데, {함수, 인자, 적용}으로 인식하기 시작하면서 편해지는 게 많아졌습니다. 그런데 이게 편한 이유가 다른 배경 지식이 생겨서 그런 건지, 이 길로 가는게 쉬운 길이어서 그런 건지는 잘 모르겠습니다. 여기서 시작하면 $<$>가 자연스러워 보였습니다. 혼자 결론에 도달하고는, 누군가가 처음 공부할 때 알려줬으면 좋았겠는데 싶었습니다. 그냥 혼자 생각입니다.

꾸벅 꾸벅 조는 건 완전 동의입니다. 제가 혼자 그 공부하면서 졸았습니다. @xtjuxtapose

2

함수형 언어의 평가와 선택

Ailrun (UTC-5/-4) @ailrun@hackers.pub

함수형 언어(Functional Language)의 핵심

함수형 언어가 점점 많은 매체에 노출되고, 더 많은 언어들이 함수형 언어의 특징을 하나 둘 받아들이고 있다. 함수형 언어, 적어도 그 특징이 점점 대세가 되고 있다는 이야기이다. 하지만, 함수형 언어가 대체 무엇이란 말인가? 무엇인지도 모르는 것이 대세가 된다고 할 수는 없지 않은가?

함수형 언어란 아주 단순히 말해서 함수가 표현식[1]인 언어를 말한다. 다른 말로는 함수가 이기 때문에 다른 함수를 호출해서 함수를 얻어내거나 함수의 인자로 함수를 넘길 수 있는 언어를 말한다. 그렇다면 이 단순화된 핵심만을 포함하는 언어로 함수형 언어의 핵심을 이해할 수 있지 않을까? 이게 바로 람다 대수(Lambda Calculus)의 역할이다.[2]

람다 대수는 딱 세 종류의 표현식만을 가지고 있다.

  1. 변수 (xx, yy, …\ldots)
  2. 매개변수 xx에 인자를 받아 한 표현식 MM(함수의 몸체)을 계산하는 함수 (λx→M\lambda x\to M)
  3. 어떤 표현식 LL의 결과 함수를 인자 NN으로 호출 (L NL\ N)

이후의 설명에서는 MMNN, 그리고 LL이라는 이름을 임의의 표현식을 나타내기 위해 사용할 것이다. 람다 대수가 어떤 것들을 표현할 수 있는가? 앞에서 말했듯이 람다 대수는 함수의 인자와 함수 호출의 결과가 모두 함수인 표현식을 포함한다. 예를 들어 λx→(λy→y)\lambda x \to (\lambda y \to y) 는 매개변수 xx에 인자를 받아 함수 λy→y\lambda y \to y를 되돌려주는 함수이고, λx→(x (λy→y))\lambda x \to (x\ (\lambda y \to y))는 매개변수 xx에 함수인 인자를 받아 그 함수를 (λy→y\lambda y \to y를 인자로 사용하여) 호출하는 함수이다.

람다 대수(Lambda Calculus)의 평가(Evaluation)

이제 문제는

그래서 람다 대수의 표현식이 하는 일이 뭔데?

이다. 위의 표현식에 대한 소개는 산수로 말하자면 x+yx + y와 같이 연산자(++)와 연산항(xxyy)로부터 얻어지는 문법만을 설명하고 있고, 3+53 + 5와 같은 구체적인 표현식을 계산해서 88이라는 결과 값을 내놓는 방식을 설명하고 있지 않다. 이런 표현식으로부터 값을 얻어내는 것을 언어의 "평가 절차"("Evaluation Procedure")라고 한다. 람다 대수의 평가 절차를 설명하는 것은 어렵지 않다. 적어도 표면적으로는 말이다.

  • 함수는 이미 값이다.
  • 함수 λx→M\lambda x \to MNN으로 호출하면 MM에 등장하는 모든 xxNN으로 치환(Substitute)하고 결과 표현식의 평가를 계속한다.

이는 겉으로 보기에는 말이 되는 설명처럼 보인다. 하지만 이 설명을 실제로 해석기(Interpreter)로 구현하려고 시도한다면 이 설명이 사실 여러 세부사항을 무시하고 있다는 점을 깨닫게 될 것이다.

  1. 함수 호출 L NL\ N에서 LL이 (아직) λx→M\lambda x \to M 꼴이 아닐 때는 어떻게 해야하지?
  2. 함수 호출 (λx→M) N(\lambda x \to M)\ N에서 NN을 먼저 평가하는 게 낫지 않나? xxMM에 여러번 등장한다면 NN을 여러번 평가해야 할텐데?

첫번째 문제는 비교적 간단히 해결할 수 있다. LL을 먼저 평가해서 λx→M\lambda x \to M 꼴의 결과 값을 얻어낸 뒤에 호출을 실행하면 되기 때문이다. 반면에 두번째 질문은 좀 더 미묘한 문제를 가지고 있다. 함수 호출의 평가에서 발생하는 이 문제에 구체적인 답을 하기 위해서는 값에 의한 호출(Call-By-Value, CBV)와 이름에 의한 호출(Call-By-Name, CBN)이 무엇인지 이해해야 한다.

값에 의한 호출(Call-By-Value)? 이름에 의한 호출(Call-By-Name)?

앞에서 말한 함수 호출에서부터 발생하는 문제는 사실 함수형 언어에서만 발생하는 문제는 아니다. C와 같은 명령형 언어에서도 함수를 호출할 때 인자를 먼저 평가해야하는지를 결정해야하기 때문이다. 즉 이 문제는 함수를 가지고 있고 함수를 호출해야하는 모든 언어들이 가지고 있는 문제이다.

그렇다면 이 일반적인 문제를 어떻게 해결하는가? 대부분의 언어가 취하는 가장 대표적인 방식은 "값에 의한 호출"("Call-By-Value", "CBV")이라고 한다. 이 함수 호출 평가 절차에서는 함수의 몸체에 인자를 치환하기 전에[3] 인자를 먼저 평가한다. 이 방식을 사용하면 인자를 여러번 평가해야하는 상황을 피할 수 있다.

또 다른 방식은 "이름에 의한 호출"("Call-By-Name", "CBN")이라고 한다. 이 방식에서는 함수의 몸체에 인자를 우선 치환한 후 몸체를 평가한다. 몇몇 언어의 매크로(Macro)와 같은 기능이 이 방식을 사용한다. 얼핏 보기에는 CBN은 장점이 없어보인다. 그러나 함수가 인자를 사용하지 않을 경우는 CBN이 장점을 가진다는 것을 볼 수 있다. 극단적으로 평가가 종료되지 않는 표현식(Non-terminating expression)이 있다면[4] CBV는 종료하지 않고 CBN만이 종료하는 경우가 있음을 다음 예시를 통해 살펴보자. 표현식 (λx→(λy→y)) N(\lambda x \to (\lambda y \to y))\ N이 있다고 할 때, NN이 평가가 종료되지 않는 표현식이라고 하자. 이 경우 CBV를 따른다면 종료하지 않는 NN 평가를 먼저 수행하느라 이 표현식의 값을 얻어낼 수 없지만, CBN을 따른다면 λy→y\lambda y \to y라는 값을 손쉽게 얻어낼 수 있다. 바로 이런 상황 때문에

CBN은 CBV보다 일반적으로 더 많은 표현식들을 평가할 수 있다

고 말한다.

모호한 선택을 피하는 방법

두 방식의 장점을 모두 가질 수는 없을까? 다시 말해서, 어떤 상황에서는 이름에 의한 호출을 사용하고, 어떤 상황에서는 값에 의한 호출을 사용할 수 없을까? 이 질문에 답한 수많은 선구자들 가운데 폴 블레인 레비(Paul Blain Levy)가 내놓은 답인 "값 밀기에 의한 호출"("Call-By-Push-Value", "CBPV")은 함수형 언어의 평가를 기계 수준(Machine level)에서 이해하는데에 있어 강력한 도구를 제공한다. CBPV는 우선 "계산"("Computation")과 "값"("Value")을 구분한다.

  • 계산 MM, NN, LL, …\ldots = 함수 λx→M\lambda x \to M 또는 함수 호출 L VL\ V
  • VV, UU, WW, …\ldots = 변수 xx

잠깐, 앞서서 함수형 언어에서 함수는 값이라고 하지 않았던가? 이는 값 밀기에 의한 호출에서 함수와 함수 호출을 종전과 전혀 다르게 이해하기 때문이다. 함수 λx→M\lambda x \to M는 스택(Stack)에서 값을 빼내어(Pop) xx라는 이름을 붙인 후 MM을 평가하는 것이고, 함수 호출 L VL\ V는 스택에 값 VV를 밀어넣고(Push)[5] LL을 평가하는 것이다. 따라서 함수 λx→M\lambda x \to M는 평가의 결과가 아닌 추가적인 평가가 가능한 표현식이 된다. 이 구분을 간결하게 설명하는 것이 다음의 CBPV 표어이다.

값은 "~인 것"이다. 계산은 "~하는 것"이다.

그렇지만 함수형 언어이기 위해서는 함수를 값으로 취급할 수 있어야 한다고 했지 않은가? 그렇다. 이를 위해 CBPV는

계산을 강제한다면(force\mathbf{force}) 계산 MM를 하는 지연된 계산인 값 thunk(M)\mathbf{thunk}(M)

을 추가로 제공한다. 이 둘 (force(V)\mathbf{force}(V)thunk(M)\mathbf{thunk}(M))을 다음과 같이 문법에 추가할 수 있다.

  • 계산 = λx→M\lambda x \to M 또는 L VL\ V 또는 force(V)\mathbf{force}(V)
  • 값 = xx 또는 thunk(M)\mathbf{thunk}(M)

CBPV를 완성하기 위해 필요한 마지막 조각은 계산을 끝내는 법이다. 현재까지 설명한 λx→M\lambda x \to ML VL\ V 그리고 force(V)\mathbf{force}(V) 는 모두 다음 계산을 이어서 하는 표현식이고, 계산을 끝내는 방법을 제공하지는 않는다. 예를 들어 λx→M\lambda x \to M의 평가는 스택에서 값을 빼내고 계산 MM의 평가를 이어한다. 그렇다면 계산의 끝은 무엇인가? 결과 값을 제공하는 것이다. 이를 위해 return(V)\mathbf{return}(V)를 계산에 추가하고, 이 결과 값을 사용할 수 있도록 M to x→NM\ \mathbf{to}\ x \to N (계산 MM을 평가한 결과 값을 xx라고 할 때 계산 NN을 평가하는 계산) 또한 계산에 추가하면 다음의 완성된 CBPV를 얻는다.

  • 계산 = λx→M\lambda x \to M 또는 L VL\ V 또는 force(V)\mathbf{force}(V) 또는 return(V)\mathbf{return}(V) 또는 M to x→NM\ \mathtt{\mathbf{to}}\ x \to N
  • 값 = xx 또는 thunk(M)\mathbf{thunk}(M)

이제 CBPV를 얻었으니 원래의 목표로 돌아가보자. 어떻게 CBV 호출과 CBN 호출을 CBPV로 설명할 수 있을까?

  • CBV 함수 λx→M\lambda x \to M와 호출 L NL\ N이 있다면, 이를 return(thunk(λx→M))\mathbf{return}{(\mathbf{thunk}(\lambda x \to M))}L to x→N to y→force(x) yL\ \mathbf{to}\ x \to N\ \mathbf{to}\ y \to \mathbf{force}(x)\ y로 표현할 수 있다. 즉, CBPV의 관점에서 CBV의 함수는 지연된 원래 계산 λx→M\lambda x \to M을 값으로 되돌려주는 계산으로 이해할 수 있고, 함수 호출 L NL\ N은 함수 부분 LL을 먼저 평가하고 NN을 평가한 뒤 NN의 계산 결과 yy를 스택에 밀어넣고 지연된 계산인 함수 부분 xx의 계산을 강제하는(force(x)\mathbf{force}(x)) 것으로 이해할 수 있다.
  • CBN 함수 λx→M\lambda x \to M와 호출 L NL\ N이 있다면, 이를 λx→M\lambda x \to M(단, 변수 xx의 모든 사용을 force(x)\mathbf{force}(x)로 치환함)과 L thunk(N)L\ \mathbf{thunk}(N)로 표현할 수 있다. 즉, CBPV의 관점에서 함수 호출은 L NL\ N은 지연된 NN을 스택에 밀어넣은 뒤 LL의 계산을 이어가는 것으로 볼 수 있다. 이 지연된 NN은 이후에 스택에서 빼내어져 어떤 이름 xx가 붙은 뒤, 이 변수가 사용될 때에야 비로소 계산된다.

다소 설명이 복잡할 수 있으나, 단순하게 말해서 CBPV는 CBV에 따른 상세한 평가 순서와 CBN 따른 상세한 평가 순서를 세부적으로 설명할 수 있는 충분한 기능을 모두 갖추고 있으며, 이를 통해 CBV 함수 호출과 CBN 함수 호출을 모두 설명할 수 있다는 이야기이다.

기계 수준(Machine level)에서의 Call-By-Push-Value의 장점

앞에서는 CBPV가 CBV와 CBN를 모두 설명할 수 있음을 다뤘다. 그러나 CBPV는 프로그래머(Programmer)가 직접 사용하기에는 과도하게 자세한 세부사항들을 포함하고 있기에, 프로그래머가 직접 CBPV를 써서 CBV와 CBN의 구분을 조율하기에는 적합하지 않다. 그렇다면 어느 수준에서 CBV와 CBN을 혼합해 사용할 때 도움을 줄 수 있을까? 바로 람다 대수를 기계 수준으로 컴파일(Compile)할 때이다. 이때는 CBPV가 가진 자세한 세부사항의 표현력이 굉장히 유용해진다.

예를 들어 람다 대수를 기계 수준으로 변환할 때 흔히 필요한 것 중 하나인 항수 분석(Arity analysis)에 대해 이야기해보자. 항수 분석은 함수가 하나의 인자를 받은 뒤 실행되어야 하는지, 혹은 두 인자를 모두 받아 실행되어야 하는지 등을 확인하여 이후에 그에 걸맞는 최적화된 기계어(Machine language)를 생성할 수 있게 도와주는 분석 작업이다. 평범한 람다 대수에서는 항수 분석의 결과를 직접적으로 표현하기 어렵다. 예를 들어 람다 대수의 λx→(λy→y)\lambda x \to (\lambda y \to y)의 경우 이 함수가 xxyy를 모두 받아 yy를 되돌려주는 함수인지 (항수가 2인 함수인지), 혹은 xx를 받아 λy→y\lambda y \to y라는 함수를 되돌려주는 함수인지 (항수가 1인 함수인지) 구분할 수 없다. 그러나 이를 CBPV로 변환한 λx→(λy→return(y))\lambda x \to (\lambda y \to \mathtt{return}(y))λx→return(thunk(λy→return(y)))\lambda x \to \mathtt{return}(\mathtt{thunk}(\lambda y \to \mathtt{return}(y)))는 각각이 무엇을 뜻하는지 분명히 이해할 수 있다.

  • λx→(λy→return(y))\lambda x \to (\lambda y \to \mathtt{return}(y))는 두 변수 xxyy를 스택에서 빼낸 뒤 yy의 값을 되돌려주는 함수(항수가 2인 함수)이다.
  • λx→return(thunk(λy→return(y)))\lambda x \to \mathtt{return}(\mathtt{thunk}(\lambda y \to \mathtt{return}(y)))는 변수 xx를 스택에서 빼낸 뒤 지연된 계산 λy→return(y)\lambda y \to \mathtt{return}(y)를 돌려주는 함수(항수가 1인 함수)이다.

이런 장점을 바탕으로 CBPV를 더 발전시킨 "언박싱한 값에 의한 호출"("Call-By-Unboxed-Value")을 GHC 컴파일러의 중간 언어(Intermediate language)로 구현하는 것에 대한 논의가 현재 진행되고 있으며 앞으로 더 많은 함수형 컴파일러들이 관련된 중간 언어를 채용하기 시작할 것으로 보인다.

마치며

이 글에서는 함수형 언어의 핵인 람다 대수를 간단히 설명하고 람다 대수를 평가하는 방법에 대해서 다루어보았다. 특히 그 중 값 밀기에 의한 평가(Call-By-Push-Value, CBPV)가 무엇이며 CBPV가 다른 대표적인 두 방법(CBV, CBN)을 어떻게 표현할 수 있는지, 그리고 CBPV의 장점이 무엇인지에 대해서도 다루어 보았다. 이 글에서 미처 다루지 못한 중요한 주제는 CBPV를 기계에 가까운 언어로 번역해보는 것이다. 여기에서는 글이 너무 복잡해지는 것을 피하기 위해 제했으나, CBPV의 장점에서 살펴봤듯 이는 CBPV에 있어 핵심 주제 중 하나이기 때문에 이후에 다른 글을 통해서라도 이 주제를 소개할 기회를 가지고자 한다. 이 글이 CBPV에 대한 친절한 소개글이었기를 바라며 이만 줄이도록 하겠다.


  1. 결과 (Value)을 가지는 언어 표현을 말한다. 예를 들어 1+11 + 122라는 값을 가지는 표현식이지만 (JavaScript의) let x = 3;나 (Python의) def f(): ...은 그 자체로는 값이 없기 때문에 표현식이 아니다. ↩︎

  2. 다만 실제 역사에서는 람다 대수의 이해와 발견이 함수형 언어의 개발보다 먼저 이루어졌다. 이런 역사적 관점에서는 (이미 많은 수학자들이 이해하고 있던) 람다 대수에 여러 기능을 추가한 것이 바로 함수형 언어라고 볼 수 있다. ↩︎

  3. 프로그래밍 언어(Programming Language)는 실제로는 치환을 사용하지 않고 환경(Environment)을 사용하는 경우가 더 많지만 설명의 편의를 위해 다른 언어들 또한 환경 대신 치환에 기반해 평가한다고 가정하겠다. ↩︎

  4. 앞서 설명한 람다 대수에서는 이를 쉽게 얻을 수 있다. 오메가(Ω\Omega)라고 부르는 표현식인 (λx→x x) (λx→x x)(\lambda x \to x\ x)\ (\lambda x \to x\ x)의 평가는 값에 의한 호출을 따르든 이름에 의한 호출을 따르든 종료되지 않는다. ↩︎

  5. 바로 이 함수 호출을 값 밀기에 기반해 해석하는 데에서 CBPV의 이름이 유래했다. ↩︎

Read more →
13
3
0

@curry박준규 더 primitive한 의미론을 포착해서 문법 요소로 만들고 그걸로 다양한 정의를 하게 하는게 낫다는 점에선 동의하는데요. 말씀하신 기준을 그대로 적용해버리면, 모든 언어들이(하스켈도 포함) 발전할수록 점점 키워드가 추가되는데, 그때마다 점점 더 안 좋아졌다고 하면 좀 이상하죠.

@bglbgl gwyng @curry박준규 적은 키워드로 표현 가능한 상황이 더 많다면 "디자인(Design)이 더 잘 되었다"고는 할 수 있다고 봅니다. 언어가 발전한다는게 디자인을 개선한다는 것과 직결되어있지 않은 경우가 더 많으니 말입니다. (많은 경우 표현력의 증대나 자주 사용되는 표현의 단순화에 더 집중하죠)

3

@bglbgl gwyng 이게 생각해보니 ‘문법이 복잡하다’, ‘문법 요소가 적다’라는 표현이 구체적이지 않은 것 같습니다. 갑자기 언어 확장이 떠오르면서 ‘문법 안 복잡한 거 맞나?’ 싶네요. 그래서 표현을 좀 바꾸면 저는 사전에 정의된 키워드가 적을 수록 좋다고 생각합니다.

3
2
2
3

[1]에서 문자열을 다룰 때 StrictTextBuilder의 성능을 비교하는 예제에서 Builder의 성능이 더 좋다고 설명한다. 그런데 내 PC에서 같은 코드를 실행했는데 결과가 반대로 나왔다. 이상해서 문자열 길이를 늘렸더니 책에서 말한대로 나왔다.

ghci> concatSpeedTest 50000
0.004451s
0.04721s
ghci> concatSpeedTest 500000
0.062405s
0.023449s
ghci> concatSpeedTest 5000000
0.511402s
0.205632s

  1. Chris Martin, Julie Moronuki, 《Sockets and Pipes》 ↩︎

3

Yacc와 같은 파서 제네레이터에 BNF를 넣으면 파서 코드가 자동으로 생성된다. 그런데 HTTP나 ActivityPub 등의 프로토콜 스펙을 입력으로 넣으면 자동으로 코드를 구현해주는 도구 어디 없나?

6
5
1
1
3

협업을 할 때 미묘하게 거슬리는 것들\ldots

  • 텍스트 파일의 마지막 줄 완성 안 하기 Posix 표준 기준으로 각 줄은 새줄 문자(line feed, '\n')로 끝나야 하며, 마지막 줄도 예외는 아님
  • 그리고 위의 일이 주기적으로 재발할 때\ldots
7

다음 글은 CBPV에 대해서 써볼까 합니다. CBV(Call-By-Value)나 CBN(Call-By-Name)은 전공자라면 한번쯤은 들어봤을 이름이지만, CBPV는 특정 분야 석박사가 아니면 들어본 적 없을 것 같네요. 하지만 실제 컴파일러 구현(GHC지만...)도 논의되고 있는 만큼 앞으로 유명해지지 않을까 싶어 미리 다뤄보려고 합니다.

어이쿠, CBPV가 무엇의 약자인지 써놓지를 않았네요. Call-By-Push-Value의 약자입니다. "Push"가 들어가는 걸로 CBV랑은 완전히 다른 것이 되는데요, 어찌 다른지는 글에서 다뤄보도록 하겠습니다.

3

다음 글은 CBPV에 대해서 써볼까 합니다. CBV(Call-By-Value)나 CBN(Call-By-Name)은 전공자라면 한번쯤은 들어봤을 이름이지만, CBPV는 특정 분야 석박사가 아니면 들어본 적 없을 것 같네요. 하지만 실제 컴파일러 구현(GHC지만...)도 논의되고 있는 만큼 앞으로 유명해지지 않을까 싶어 미리 다뤄보려고 합니다.

6
2
0

브라우저 탭 라이프

사이드 탭
트리 탭
탭 잠그기
탭 배경색 바꾸기
탭 타이틀 바꾸기 및 고정

다 설치했다니, 이제사 탭 뭉치에서 방황하는 시간이 좀 줄어드나 싶네요.

가상 데스크탑으로 구분, 브라우저 창으로 구분, 그런데도 한 브라우저당 탭을 몇 십개씩 열어 놓습니다. 마음의 여유가 없어지니, 한 주제를 오래 못 보나 싶습니다. 언제 바꾸긴 해야 할 것 같은 탭 라이프인데, 외부 요인이 생겨야 가능할 것 같습니다.

2
1

@curry박준규 Dependent Haskell은 흥미로운 내용을 다루기에는 아직 너무 갈 길이 멀고... 그렇다고 동기만 다루자니 좀 심심하네요. 아마 Agda나 Coq등을 조금 다뤄보지 않을까 싶습니다. 관련 내용으로 Dependent Haskell을 좀 언급할 수는 있겠습니다.

0

같은 것과 같지 않은 것에 대해서 짤막한 글을 써 보았습니다. 오랜만에 국어로 쓰는 글이라 잘 읽힐지 모르겠네요.

0

같은 것을 알아내는 방법

Ailrun (UTC-5/-4) @ailrun@hackers.pub

이 글은 일상적인 질문에서부터 컴퓨터 과학의 핵심 문제에 이르기까지, '같음'이라는 개념이 어떻게 적용되고 해석되는지를 탐구합니다. 특히, 두 프로그램이 '같은지'를 판정하는 문제에 초점을 맞춰, 문법적 비교와 $\beta$ 동등성이라는 두 가지 접근 방식을 소개합니다. 문법적 비교는 단순하지만 제한적이며, $\beta$ 동등성은 프로그램의 실행을 고려하지만, 계산 복잡성으로 인해 적용이 어렵습니다. 이러한 어려움에도 불구하고, 의존 형 이론에서의 형 검사(변환 검사)는 $\beta$ 동등성이 유용하게 활용될 수 있는 중요한 사례임을 설명합니다. 이 글은 '같음'의 개념이 프로그래밍과 타입 이론에서 어떻게 중요한 역할을 하는지, 그리고 이 개념을 올바르게 이해하고 구현하는 것이 왜 중요한지를 강조하며 마무리됩니다.

Read more →
5
2
2
0

@lionhairdino 국어 글쓰기 재활을 좀 해 보아야겠네요. 일전의 블로그 투고 연재의 "실패"는 너무 큰 조각을 한 번에 쓰려고 했기 때문 아닌가 싶은데, 이런 매체에서의 글쓰기는 더 세밀한 조각으로 나눌 수 있지 않을까 싶네요.

0
0

기능이 여럿 있는데, 그 상세를 잘 모르겠는 것이 많군요. 이를테면 "공개"와 "조용히 공개"의 차이점이 제게는 직관적이지 않네요. 무슨 차이인지 아시는 분이 있다면 알려주시면 감사하겠습니다.

0
0