https://gall.dcinside.com/mgallery/board/view/?id=github&no=39739


보니까 주딱 의견이랑 내 의견은 Moggi의 논문을 어떻게 해석해야 하는가, 보다 정확하게는 그 논문들에서 언급되는 Computation(계산)과 Notion of computation(계산개념)의 의미를 어떻게 이해해야 하는가에서 충돌하는것 같음.


주딱 의견 : Moggi 이전의 계산은 완전히 형식적으로 이해되지 못한 모호한 대상이었다. Moggi가 Monad를 사용해 그것에 수학적 정의를 내림으로써 계산의 범주가 재정의된 거다. lambda calculus의 체계를 나타내는 카테고리 기반의 모든 Kleisli 카테고리가 계산의 체계를 나타낸다. 그리고 Kleisli 카테고리를 만드는 모든 T, 즉 모든 모나드가 계산개념이다. 계산개념 자체를 Moggi가 그렇게 재정의했다.


내 의견 : Moggi의 관심사는 어디까지나 실패 가능성, 비결정성 또는 부작용을 가질 수 있는 실제 프로그램을 정확하게 묘사할 수 있는 카테고리를 찾는 것이었다. 이른바 Categorical semantics of computations은 그것에 대한 일반적인 답 또는 답을 생성하는 프레임워크이며 이 맥락에서 계산(Computation)이란 단지 상술한 실패 가능성, 비결정성 또는 부작용을 가질 수 있는 프로그램의 함수들을 느슨하게 일컫는 용어로 사용되고 있을 뿐이다. 계산이라는 말 자체를 재정의한다거나 하는 의도 따위는 Moggi에게 없었다.


윗 글의 코멘트에서 내가 아마 주딱이 맞을 것 같다고 한 건 주딱 의견이 수학자가 할 만한 일에 대한 묘사로써 충분히 그럴듯했고 주딱이 너무 자신있게 그걸 이야기했기 때문임. 


하지만 실제로 그런가? 난 Moggi의 논문을 다시 읽어봤다. 



우선 ①, 초록을 보자. 요약하자면 지금까지 람다 칼큘러스에서는 프로그램을 그냥 함수로 보고 프로그래밍 언어 같은 것들을 분석했는데 이 방법에는 하자가 있다. 이 논문에서 우리는 계산을 나타낼 수 있는 카테고리를 개발했고 이것이 다양한 계산개념을 나타낼 수 있는 프로그램들에 대한 정확한 분석의 기반을 마련해 줄거다. 이런 얘기임. 


②도 비슷한 얘기를 하고 있음. 기존 접근은 실제 프로그램이 가질 수 있는 실패가능성이나 비결정성, 부작용을 고려하지 않는다는 하자가 있고 그걸 해결하겠다. 


그리고 "Categorical semantics of computations"을 개발하겠다고 하는데 이건 "Computation" 들이 이루는 체계를 나타낼 수 있는 카테고리를 만들겠다는 걸 뜻함. 결국 이 말의 의미는 Computation의 의미에 의존하는데 문맥상 이 Computation은 당연히 위에 언급한 실패가능성이나 비결정성, 부작용 같은 걸 갖는 함수라고 봐야 하지 않나.


그 아래에는 features of computation이라는 말이 비결정성이나 부작용, continuation 등의 개념을 통칭하는 의미로 사용되고 있는데. 적어도 이 문장에서 Computation이라는 말은 순수하지 못한 실제 프로그램의 함수들을 느슨하게 일컫는 것이 거의 확실해 보임.


개인적으로 ③ 을 어떻게 생각하는지 묻고 싶다. 나한테는 도저히 이 부분이 Computation과 Notion of computation을 함께 정의하는 부분으로는 안 보임. 느슨하게 정의된 Computation의 개념을 기반으로 Notion of computation을 정의하는 부분이지. 애초에 지금 모나드도 Kleisli도 안 나왔는데 Computation을 주딱 말대로 명확하게 정의하는 것 자체가 불가능함. 


④에도 주목할 부분이 있는데 Kleisli triple이 T의 필요충분조건이 아니라 필요조건으로써만 언급되고 있다는 것임. 내가 모든 계산개념이 다 모나드는 아니라고 했을 때 난 이걸 말했던 거다. 



그리고 이 논문에서 계산이나 계산개념의 정의에 관계된 것으로 이해될 수 있는 내용들은 그냥 여기까지임. Computation이나 Notion of computation을 형식적으로 재정의하는 부분은 어디에도 없음. 주딱 말대로 Moggi가 계산 또는 계산개념 자체를 카테고리 이론적으로 재정의하고자 했다면 당연히 논문 어딘가에는 그 단어들을 재정의하는 부분이 있어야 하는데 그냥 없다고.


나중에 일반적인 T에 대해 메타 언어같은거 가지고 놀기는 하는데 그걸 가지고 명확하게 계산이나 계산개념을 재정의하는 등의 시도는 없어서 이걸 Computation을 정의했다고 해야 하는 건지 아리까리함. 


Conclusion 파트에서는 다를까? Moggi가 계산개념을 재정의했다면 적어도 결론 부분에서는 그걸 언급할 법도 한데 없음. 대신 이런 게 있지.





Notion of computation이 모나드를 통해 형식적으로 재정의된 거라면서? 여기서는 모나드가 그냥 Notion of computation을 모델링하기 위해 중요한 거라고 하는데? 지금 Computation을 재정의하는 부분이 논문에 한개도 없으며 결론에서도 모나드와 Notion of computation을 느슨하게 연결짓기만 하는데 이게 모나드를 통해 계산개념을 확실하게 재정의한 논문임?



Moggi의 1989년 논문도 봤는데 여기에는 주딱 의견을 지지하는 듯한 부분도 있긴 함. ① 보면 "Categorical semantics of computations"이 "Computational model"과 무관하게 프로그램에 대한 정확한 분석을 하게 해 준다는 얘기가 나오는데 "Computational model" 은 ④에서 모나드 기반의 정확한 정의가 나옴. 


그러나 모나드나 Kleisli triple이 T가 계산을 나타내기 위한 필요조건으로써만 소개되는 건 이 논문에서도 여전하며 정작 중요한 Computation이나 Notion of computation을 형식적으로 재정의하고자 하는 시도는 이 논문에도 전혀 보이지 않음. 오히려 ⑤ 같은 걸 보면 저자가 Notion of computation을 대충 실제 프로그래밍 언어에서의 비 순수성들을 나타내는 느슨한 개념으로 사용하고 있다는 게 여실히 드러남. 




Moggi가 실제로 계산을 모나드를 통해 재정의하고자 했는지 안 했는지와 무관하게 그러한 재정의가 매력적인 건 맞아. 문제는 계산이나 계산개념이라는 단어를 그런 의미로 쓰겠다는 명확한 논의나 공감대가 학계에서든 하스켈 커뮤니티에서든 있기는 했냐는 거지.


Just as the type Value represents a value, the type M Value can be thought of as representing a computation. The purpose of unitM is to coerce a value into a computation; the purpose of bindM is to evaluate a computation, yielding a value.


Wadler의 이 말은 그러한 명확한 논의를 바탕으로 씌여진 얘기임? 확신해? 애초에 그런 논의가 있었다고 쳐도 Wadler는 그걸 설명해 주지도 않는데 이게 이해가 될 수 있는 문장임? 주딱한테 이해가 되는지 안 되는지는 관심 없고 정말로 모나드를 처음 접하는 이들이 이런 문장들을 보고 혼란을 느끼지 않을 거라고 생각함?



그리고 계산을 모나드를 통해 형식적으로 재정의한다 쳐도 왜 그런식으로 재정의함? T를 계산개념이라고 하는건 이해가 감. 그런데 T<A>가 계산이야? 정말로 Optional<A>와 List<A>를 계산이라고 부르는 게 계산에 대한 바람직한 형식적인 정의야? 


"우리의 직관이 리스트를 계산이라고 받아들이지 못했다면 그건 우리의 계산개념에 대한 이해가 부족하기 때문이니 우리의 직관을 고쳐야 함. 리스트에도 계산의 관점을 적용한다는 전에는 없던 사고를 할 수 있게 해주니 계산개념이라는 관점이 유용한거임."


이거 진짜로 확신해? 잘 생각해봐. 이거 생각보다 많이 이상하다? 람다 칼큘러스의 semantic category는 값과 함수들로 이루어진 체계잖아? 계산의 semantic category라면 값과 계산들로 이루어진 체계가 되어야 하는 것 아닐까? 그렇다면 계산을 나타내는 건 그 카테고리의 사상들, 즉 T<A>를 반환하는 함수들이잖아? 왜 함수가 아니라 T<A> 자체를 계산을 나타내는 타입으로 봄? 그게 정말 모나드 가지고 계산을 형식적으로 정의하는 바람직한 방법일까? T<A>가 계산을 나타낸다는 건 그냥 내가 지적했듯이 Moggi가 논문에서 T<A>를 반환하는 표현식이 계산을 나타낸다는 의미에서 T<A>가 계산의 타입이라고 한 걸 오해해서 생긴 오개념 아님?


주딱이 말하는 리스트에도 계산의 관점을 적용한다는 그 "전에 없던 사고" 는 뭐임? 그건 정말로 주딱의 사고를 더 풍요롭게 해주고 있는 게 맞음? 더 엉성하고 혼란스럽게 만들고 있는거 아님?


그 사고가 어떤 건지 나도 대충은 앎. 그래서 알기 때문에 말하는 거다. 그거 아무짝에도 쓸데없는 뜬구름 잡기임. 그런 것 전체가 본래는 그렇게 복잡하지도 않은 모나드 개념에 대한 불필요한 신비화이며 내가 내 글에서 지적한, 지난 25년 간 모나드에 대한 정합적인 설명을 완전히 불가능하게 한 백해무익한 환상의 근원인 거다.



요컨대 계산을 형식적으로 재정의한다는 생각은 매력적이긴 함. 문제는 그러한 재정의가 Moggi에 의해서든 누구에 의해서든 전혀 정확한 의미로 합의된 적이 없는 것으로 보이며 그 결과 사람마다 각자 다른 의미로 계산이라는 단어를 사용하고 있다는 거다. 그것도 모자라 가장 흔히 쓰이는 그 단어의 의미가 설명하기 쉽기는 고사하고 애초에 바람직한 것인지조차 의심스러운 상황임. 이 상황이 아무 문제가 없고 전혀 시정될 필요가 없다고 생각한다면 난 더 이상 할 말이 없음.


그래놓고는 사람들이 구체적인 대상들을 다루는건 잘 하는데 이런 추상적인 개념은 어려워 한다느니 그래도 하스켈은 권유해야 된다느니 모나드 이해 안되면 그냥 모나드 모른채로 하스켈을 하면 되는데 그게 잘 안된다느니... 안돼 돌아가 공감 안해줘. 


모나드가 뭐 별거냐? 그냥 타입 컨스트럭터 T 중에서 A->B 타입의 함수를 T<A>->T<B>타입으로 변환할 수 있으며 A에서 T<A>로의 형 변환과 T<T<A>>에서 T<A>로의 형 변환이 모두 있는 게 모나드임. 그게 프로그래밍에서 유용한 건 T가 모나드일 경우 A에서 T<B>로 가는 함수들이 A에서 B로 가는 함수의 다양한 논리적 확장을 나타낼 수 있으며, 이 확장된 함수들을 합성할 수도 있기 때문임. 난 그걸 그냥 확장된 함수라고 불렀고 계산은 그것 중에서 비 순수 함수를 나타내는 일부 부분집합만을 나타내는 용어로 썼는데 사실 둘이 같은거면 그냥 계산이라고 하면 되니까 더 좋지. 도대체 뭐가 문제임?


지금까지 모나드 튜토리얼들이 꼴아박은게 추상적인 개념이 어려워서일까? 그냥 그 튜토리얼들의 모나드 설명들이 얼척없이 나빠서다. 모나드의 추상성이 아니라, 지금 본 것과 같은 불필요한 신비화나 횡설수설이나 즐기는 문화가 작금의 모나드 튜토리얼 비극을 만듬. 난 그걸 끝낼 수 있다고 보고 작업하고 있는데 왜 그게 안된다는 패배주의에 공감해줘야 하나. 



끝으로 설령 확장된 의미에서의 계산개념이 모든 모나드에 대한 설명이 된다 해도 난 그것만으로 모나드를 설명하려는 시도가 여전히 실수라고 생각함. 왜냐하면 그 설명은 가장 중요한 한 가지 측면에서 여전히 모나드의 일부밖에 설명하지 못하고 있기 때문이다. 


그 측면은 목적이라는 측면이다. 계산이라는 단어는 애초에 각종 Effect(주딱의 표현을 빌렸음)를 가진 프로그램을 순수 함수로 나타내 보려는 시도 속에서 만들어졌고, 아무리 재정의된다 해도 그러한 목적의 맥락에서 벗어날 수 없음.


모든 Kleisli 카테고리가 어떤 Effect를 가진 계산을 나타내기 위해 쓰이리라는 법은 없다. 모나드는 다른 종류의 확장된 함수를 나타내는 데도 충분히 응용될 수 있음. List 모나드만 해도 실제로는 비결정적인 계산을 나타내는 데보다는 그냥 결과가 여러 개인 함수들을 나타내는 데 더 많이 쓰이지 않나. 물론 그것도 넓은 의미에서 계산이라고 불릴 수 있지만 Effect와 거의 무관한 이런 맥락에서 계산이라는 용어를 쓰는 건 단지 혼란스러울 뿐임. 그 계산이라는 단어가 원인이 되어서 모나드를 오직 Effect를 캡슐화하는 도구로만 한정시켜서 보거나 이해하는 경우들을 너무 많이 봤다.


그러니까 그 Effect 같은 단어가 주딱 생각처럼 완벽하게 추상적이고 거의 의미가 없을 정도로 일반적인 개념으로 이해되면 다행인데 대부분의 사람들은 그냥 부작용 같은거 생각한다고. 


내 주장은 그냥 A→T<B>가 "확장된 함수" 를 나타낸다고 설명하고 그것의 한 사례로써 부작용을 나타내는 모나드들을 설명하는 게 훨씬 낫다는 것임. 그렇게 설명을 안 하고 꼭 모든걸 계산, Effect에 연관지으려 하니까 모나드가 Effect를 나타내는 거라 함수형 언어에서만 쓸모가 있다느니 그래서 명령형 프로그래머들한테는 모나드 설명 못한다느니 하는 오류들이 생겨나는 것임. 명령형 프로그래머들도 Optional이나 List같은 모나드들 한번 설명해주면 멀쩡하게 잘 알아들음. 




이하는 주딱의 지적들에 대한 내 답변임.




0. Moggi가 모나드 전부를 계산 개념이라고 부르지 않았다는건 레퍼런스 있음? 정확히는 lambda calculi의 시멘틱으로 쓰이는 카테고리에서의 모나드중에 계산 개념이라고 불리지 않는게 있는지 의심스러움



→ 나는 이 글(https://dkalemis.wordpress.com/2014/03/22/trees-as-monads/)에 소개된 두 번째 트리 모나드를 예로 들고 싶음. 물론 이것도 넓은 의미에서 계산개념이라고 부를 수 있겠지만 Moggi도 이걸 계산개념의 사례로 생각했을지는 의심스러움. 




1. Moggi가 쓴 논문은 effect를 모나드로 해석할 수 있다는 얘기를 하는거고 모나드는 이미 수학적으로 엄밀하게 정의되는 대상이니 독자에게 해설하려는 목적이 아니라면 굳이 모나드를 재정의할 필요는 없음



→ 이 얘기는 왜 나온지 모르겠네.




2. 나랑은 계산개념과 모나드의 관계를 보는 관점이 완전히 다른것 같은데, 내 이해로 모나드는 effect를 가질 수 있는 계산 그 자체이고, 계산개념은  (lambda calculi의 시멘틱 카테고리에서의) 모나드에 이런 관점을 투사한 것임. Moggi 이전의 계산은 완전히 형식적으로 이해되지 못한 모호한 대상이었고 Monad를 사용해 수학적 정의를 내리고 계산개념이라는 이름을 붙임으로써 계산의 범주가 재정의되었다고 생각함.


그러니까 계산개념으로 모나드를 이해하는게 아니라 모나드로 계산개념을 이해하는게 맞음. 우리의 직관이 리스트를 계산이라고 받아들이지 못했다면 그건 우리의 계산개념에 대한 이해가 부족하기 때문이니 우리의 직관을 고쳐야 함. 리스트에도 계산의 관점을 적용한다는 전에는 없던 사고를 할 수 있게 해주니 계산개념이라는 관점이 유용한거임.


논리적으로는 모나드가 먼저 정의되고 계산개념이 뒤따르는거지만, 프로그래머한테는 모나드 같은 추상적 개념이 익숙하지 않으니 계산을 통해 모나드를 이해하려는 것이고. 물론 이렇게 하면 모나드에 대한 피상적인 이해밖에 되지 못하니 그게 전부라고 생각하는건 곤란하지만.


내가 보기엔 Moggi나 Wadler의 설명은 완벽하게 이해 됨. 처음 보는 사람한테 뜬구름 잡는 소리 처럼 들릴 수는 있겠지만 적어도 틀렸거나 무의미한 말은 아님.



→ Effect가 뭘 말하는 거임? 모든 모나드의 Kleisli 사상을 포함하는 의미에서의 Effect가 정의가 가능하긴 한거임? 위의 트리 모나드는 무슨 Effect를 나타냄?


하여튼 내 답변은 위에 쓴 거 그대로임. 계산 자체를 모나드를 통해 형식적으로 재정의한다는 아이디어는 멋있긴 한데 Moggi의 의도 중에 그런 게 있었는지는 전혀 확실치 않음. 적어도 내가 보기에 Moggi의 논문들은 실제 프로그램을 묘사할 수 있는 람다 칼큘러스 기반의 체계를 만들어 주는 프레임워크를 제공하는 것으로밖에 안 보임. 


그리고 계산을 모나드를 통해 형식적으로 재정의하더라도 T<A>가 계산을 나타낸다는 정의는 설명하기도 힘들거니와 애초에 계산의 형식적인 정의로써 과연 적절하기는 한 건지부터 진지하게 따져 봐야함. 사람들이 그 설명을 이해 못하는 건 그게 추상적이기 때문이 아니라 이상해서임. 그런 식으로 계산을 정의해놓고 그 정의를 기반으로 모나드를 이해시키려고 하고 있으니 모나드 튜토리얼들이 꼬라박지 않을 수가 있나. 모나드는 무죄야.


주딱한테 완전히 이해 되고 말고가 중요한 게 아님. 처음 보는 사람한테 그 시공이 뒤틀린 계산개념 어떻게 설명할거야? 그 백해무익한 "전에 없던 사고" 만 어디다 갖다버리면 모나드 설명 되는데 안 버릴거야?




3. bind가 수학적으로 join에 비해 덜 깔끔하긴 하지만, 계산개념 관점에서 이해하기에는 join보다 직관적임. join을 이해하려면 m (m a) 부터가 난점이다. m이 중첩되는게 무슨 의미인데? State/IO 모나드의 경우 bind는 계산을 시퀸셜하게 이어준다는 직관적인 설명을 줄 수 있지만, join은 외려 힘듬. 다만 일반적인건 아니고 리스트 같은 경우엔 join이 이해하기 더 쉽다는데에 동의함. 그런데 이 경우 너도 그렇듯이 계산개념의 관점으로는 잘 생각되지 않지. 나는 이 부분에 있어선 그냥 bind, join, kleisli composition을 다 소개해야 한다고 생각함.



→ 우선 코멘트에 쓴 말부터 그대로 옮기겠음. 계산개념부터가 거의 이해가 불가능한 게 되어버린 시점에서 그것을 토대로 이해하기에는 bind가 join보다 쉽다는 게 의미가 있나? 애초에 그거 사실이기는 함? IO 모나드에서 join은 의미가 아주 명확함. A를 반환하는 IO 프로시저를 반환하는 IO 프로시저는 당연히 A를 반환하는 IO 프로시저로 볼 수 있지. 심지어 이 논리는 일반화도 가능함. A를 반환하는 계산을 반환하는 계산이 있으면 A를 반환하는 계산을 만들 수 있는 건 당연한 것 아닌가? 


T A가 계산이든 뭐든 간에 그게 A의 뭐를 나타내는 시점에서 그 뭐가 명확하기만 하면 그걸 두번 겹치는 건 전혀 어려운 게 아님. 안 명확한 게 문제고 이건 join이든 bind든 똑같이 문제가 됨. IO 모나드 설명하는 문제를 실제로 고민해 봤고 여러 번 설명해 본 적도 있는 내가 보기에는 그걸 bind로 더 쉽게 설명할 수 있다는 얘기는 그냥 웃김. 




4. 모나드에 대한 비유적 설명이 입문자에게 도움이 되는지에 대해서는 나도 회의적임. 결국 모나드를 제대로 이해하는데에 핵심적인건 개별 모나드들에 대한 사례 분석과 수학적 정의를 제대로 파악하는 것이고, 이 두가지가 병행된다면 저런 비유적 설명도 마냥 나쁘진 않다고 생각함. 부정적인 결과는 보통 저 두가지를 제대로 안한 경우고.


사실 추상적인 개념들은 대부분 이런 방식으로 배워야 됨. 근데 복잡하더라도 구체적인 대상들을 다루는건 잘 하는데 이런 추상적인 개념은 어려워 하는 사람들이 꽤 많다. 경험상 프로그래머들도 그럼. 여기서 결국 모나드를 이해하기를 포기하는 사람들이 나옴. 근데 하스켈 커뮤니티 입장에서는 모나드를 이해하지 못한 사람한테도 하스켈은 권유해야 됨. 그럼 그냥 모나드 모른채로 하스켈을 하면 되는데, 다들 그게 잘 안되는것 같다.



→ 좋은 비유는 도움이 되지. 모나드에 대해서는 특히 좋은 비유가 드물어서 그렇지. 이건 딱히 내 글에 대한 반박도 아닌것 같으니 넘어가겠음. 뒤쪽 얘기는 은근슬쩍 나한테 모나드 쉽게 설명하는 게 불가능하다는 관점을 동의시키려는 것 같은데 전혀 동의 안함. 끝.