커링(currying)

본문에서는 transfer 함수가 Account, Account, Int 타입의 인자 3개를 받고 IO () 리턴하는 함수로 설명했다. 이런 해석 방식으로도 하스켈 함수를 이해하고 사용하는 데에는 아무런 지장이 없지만 하스켈에서 ->을 보다 정확히 이해하기 위해서는 커링(curring)의 개념을 알아야 한다.

하스켈은 C/C++, 자바 등 일반적인 명령형(imperative) 언어와 달리 함수가 제 1 클래스이다. (파이썬과 루비 같은 최신 스크립트 언어는 예외다.) 여기서 제 1 클래스라고 하면 다른 타입과 마찬가지로 함수 역시 함수의 인자로 넘길 수 있고 리턴 값으로 함수를 리턴할 수도 있다는 뜻이다. 그리고 ->는 결합의 방향이 오른쪽이다.

따라서 Account -> Account -> Int -> IO ()는 실제로 (Account -> (Account -> (Int -> IO ())))를 뜻한다. 이렇게 괄호로 묶은 (Account -> (Account -> (Int -> IO ())))를 다시 보면 한 가지 흥미로운 사실을 발견할 수 있다. 이 함수는 Account 타입을 하나 인자로 받아서 (Account -> (Int -> IO ())) 타입의 함수를 리턴하는 함수로 볼 수도 있기 때문이다. 리턴된 함수의 타입인 (Account -> (Int -> IO ())) 역시 또 다른 Account를 인자로 받고 (Int -> IO ())를 타입으로 가지는 또 다른 함수를 리턴한다. 마지막으로 이 함수에 Int 인자를 넘기면 IO () 타입을 리턴한다.

즉, 우리가 처음에 3개의 인자를 받는다고 생각했던 transfer 함수는 실제로는 1개의 인자를 받는 여러 개의 함수로 이해할 수도 있다. 이처럼 여러 개 인자를 받는 함수를 1개의 인자를 받는 여러 함수로 변화시키는 것을 커링(currying)이라고 부른다.

Joe Armstrong과의 인터뷰

Thinking Parallel이란 블로그에서 작년 초에 Erlang을 만든 Joe Armstrong과 Parallel Programming에 대한 인터뷰를 나눈 것이 있더군요.

Joe Armstrong은 Erlang의 창시자답게 shared-memory programming과 message passing 중 어떤 방식이 더 좋냐는 질문에 shared memory에서 lock 잡다가 문제 생기면 회복할 방법이 없음을 강조하며 적극적으로 message passing 스타일을 옹호하고 있습니다. 대신 trasactional memory는 살짝 message passing과 같이 끼워서 괜찮다는 식으로 넘어가고 있습니다.

parallel programming의 미래가 pure message passing에서 온다는 부분은 저는 동의하기가 약간 어렵습니다. pure message passing의 많은 장점에도 불구하고, 여전히 mutable한 shared state로 표현하는 데이터 구조가 가장 직관적인 경우가 너무 많기 때문입니다. 일례로, 웹개발자가 가장 애용하는 DOM tree는 타고 나기를 mutable shared state의 집합이니깐요.

pure message passing을 이용한 간단한 parallel programming model도 Erlang의 장점인 것을 분명하지만, 저는 분산 컴퓨팅(distributed computing)이나 결함허용(fault-tolerant) 관련된 기능을 프로그래밍 언어에 잘 녹여 넣은 부분을 더 높게 평가합니다. 실제로 Ericsson의 스위치, 라우터 장비에서 안정적으로 돌아간 경력이 있기도 하고요.

멀티코어 시대의 새로운 분산 프로그래밍 모델은 앞으로 소프트웨어가 풀어야할 가장 큰 과제입니다. Erlang이 좋은 모델을 제시한 것은 분명하지만, 멀티코어 문제가 Erlang이 이야기하는 pure message passing 모델만으로 해결될 것 같지는 않다는 게 제 생각입니다.

똑똑하고 100배 일잘하는 개발자 모시기

위키북스에서 “조엘 온 소프트웨어” 저자로 유명한 조엘이 쓴 똑똑하고 100배 일잘하는 개발자 모시기를 보내주셔서 읽어봤습니다. 개발자를 선발하고 개발 조직을 운영하는 방법에 대해 저자의 생각을 아주 명료하게 전달하고 있는 책이더군요.

초일류 프로그래머는 초일류 제품을 만들고 회사를 먹여 살리기 때문에 개발자를 뽑는 일은 사운을 좌지우지할 정도로 중요한 일임에는 틀림이 없습니다. 가장 잘하는 개발자와 못하는 개발자의 생산성 차이가 10배 이상이라는 연구 결과는 아주 많습니다. 10x Software Development

하지만 작은 회사에서 귀하신 몸인 “슈퍼 개발자”를 모셔오기란 무척 힘들기 때문에 조엘의 회사인 포크 크릭 소프트웨어사는 아직 졸업이 한참 남은 대학생들을 인턴으로 받아서, 감동과 환희를 선사한 후에 끈끈한 관계를 유지해서 회사로 데려오는 전략을 많이 쓰고 있습니다.

조엘의 논리는 괜찮은 개발자들은 이미 대학교 1-2학년 때 성숙한 경지에 접어든다는 것이죠. 심지어 고등학교 때부터 미리 계약해 두고 후원하는 것까지 생각하고 있다는 조엘입니다.

저도 예전에 상당한 쇼킹한 후배에 대한 기억이 있습니다. 대학 신입생 환영회에서 이야기하다보니 한 후배는 자기가 중고등학교 때 이미 운영체제로 FreeBSD와 리눅스를 쓰고 C/C++, 자바도 아닌 헤스켈로 코딩을 해왔다더군요. 특별히 옆에서 누가 가르쳐준 것도 아니고 그냥 혼자서 말이죠. (그냥 한 두번 HelloWorld 짜본 것이 아니고 상당히 잘한다는 사실은 나중에 알게 되었습니다)

컴퓨터도 음악이나 미술처럼 태어날 때부터 신동들이 있는 걸까요? 메릴랜드에서 교환학생 할 때도 Cyclone이랑 언어 만드는 쪽에 연구참여 하려고 찾아가서 Cyclone 연구는 주로 누가 하냐고 물었더니, 메릴랜드대, 하버드대, AT&T와 더불어 고등학생 1명이 한다더군요. 처음에는 영어가 딸려서 잘못 들은 줄 알았습니다.

리눅스에도 예전에 커널 maintenance 하는 애중에 굉장히 어린 친구가 있었던 걸로 아는데, 암튼 슈퍼 히어로가 많은 분야인 것 같습니다. 중언부언했는데, 결론을 말하자면 그런 슈퍼 인재를 잡는 회사는 땡잡는 다는 것 정도랄까요?

카테고리 이론(Category Theory)

카테고리 이론(Category Theory)은 컴퓨터공학과 학부 교과목에서 잘 가르치지 않지만 프로그래밍 언어를 비롯한 컴퓨터과학 여러 곳에서 이용되는 수학입니다. 학교 다닐 때 수학 공부 열심히 안 했기 때문에 최근에 Benjamin C. Pierce의 Basic Category Theory for Computer Scientists를 읽어보고 있는데 covariant/contravariant functor를 부분을 보다가 문득 익숙한 용어라는 생각이 들었습니다.

알고보니 객체지향 언어의 타입을 논할 때 서브클래스의 메서드가 상위 클래스 메서드의 리턴 타입이나 인자 타입을 변경하는 규칙을 말할 때 쓰는 covariant 혹은 contravariant 타입 시스템(type system)이 카테고리 이론에서 빌려온 말이더군요. 어원 이런 거 제대로 알려면 역시 사람은 공부를 해야하나 봅니다.

전산 입문도 함수 언어로

포항공대는 2008년부터 전산 입문 과목인 CS101을 실용적 함수 언어로 알려진 OCaml로 가르치기 시작했습니다. 2008학번 1학년 학부 학생은 C나 자바보다 함수 언어를 먼저 배우게 되었군요. 프로그래밍 언어 과목이 아니라 전산 입문 언어를 함수 언어로 가르치는 사례는 처음이 아닐까 싶은데 이 학생들이 졸업할 때쯤은 어떻게 소감을 밝힐지가 무척 궁금합니다.

그리고 보니 작년 초에 OCaml Tutorial 번역하다가 급성 인후염으로 앓아 누운 다음에 재개를 못해서 아직도 내버려둔 상태네요 ㅠ.ㅠ 누가 여력 있으시면 마무리 해주시면 좋을 듯.

정적 타이핑과 동적 타이핑

마이크로소프트의 IronRuby 팀에서 No Borg-like release train for Ruby on .NET이라는 글을 통해 올해 말까지는 IronRuby 1.0을 완성하겠다는 발표를 했습니다. 루비가 제대로 된 언어 명세도 없다보니 명확한 시멘틱이 정의가 안 된 부분이 많고 구현마다 다른 부분을 어려움으로 호소하고 있습니다. 아 그리고 루비의 가장 중요한 어플리케이션이 Rails인 만큼 IronRuby on Rails도 중요하게 생각하고 있는 것 같습니다.

그런데 이 글의 마지막 문구에서 왜 .NET 개발자가 루비에 관심을 가져야 하느냐는 질문에 Iron Ruby 프로젝트 리더인 John Lam 말이 정적 타이핑(static typing)하는 언어는 동적 타이핑(dynamic typing)하는 언어보다 유지보수 하기가 힘들다는 말을 했습니다. 유지 보수가 힘든 이유는 변경이 힘들기 때문이라고 이야기했습니다.

Finally, why should .NET developers bother with Ruby? According to Lam: “You spend less time writing software than you spend maintaining software. Optimizing for writing software versus maintaining software is probably the wrong thing to do. Static typing makes it harder to maintain software because it’s harder to change it.”®

저는 정반대로 생각하기 때문에 순간 글을 잘못 읽었나 착각에 빠졌습니다. 이와 관련해  Haskell Cafe에도 Dynamic typing makes you more productive? 라는 글에 내용이 올라오면서 많은 사람들이 자기 생각을 달았습니다. 요약하면, C++, Java, C# 처럼 어설픈 정적 타이핑하는 언어를 보던 사람들에게는 루비의 동적 타이핑이 굉장한 장점으로 보일 수 있는 것은 사실입니다만 제대로 된 정적 타이핑을 하는 언어를 보면 그런 생각을 바꿀 것이라는 의견입니다. 물론 헤스켈 커뮤니티 메일링 리스트니깐 당연히 그렇게 이야기하겠지만요.

결론: 정적 타이핑의 이름을 더럽힌 자바랑 C# 나빠요.

캐릭터셋 인코딩 탐지(Charset Encoding Detection)

캐릭터셋 인코딩은 개발자를 지속적으로 괴롭히는 몬스터 중에 하나입니다. 일단 규격 자체가 많은 것은 첫 번째 괴로움이고 규격을 안 지키는 사람이 많다는 사실은 두 번째 괴로움입니다. XML이나 HTTP 헤더처럼 인코딩 정보를 명시적으로 보내주는 경우는 그나마 상황이 나은데, 인코딩을 전혀 알 수 없는 것 중에 하나가 자막 파일입니다.

국내에서 많이 쓰는 SMI 파일의 경우 .KRCC니 .ENCC니 하면서 언어는 지정하는데 정작 어떤 인코딩으로 파일이 인코딩되었는지 정보가 없습니다. 국내에 돌아다니는 SMI 파일은 대부분 EUC-KR을 쓰긴 하지만 꼭 한국어만 SMI로 만들라는 법도 없으니깐요. 외국에서 많이 쓰는 SRT 포맷은 SMI 포맷보다 더 간단합니다. 어떤 언어인지도 모르고 인코딩도 모르고 다짜고짜 시간-자막이 반복되는 포맷입니다.

이런 경우에 사용할 수 있는 라이브러리가 Universal Encoding Detector입니다. 원래 Mozilla에서 인코딩이 없는 페이지의 캐릭터셋을 자동으로 찾아내기 위해 시작한 프로젝트입니다. A composite approach to language/encoding detection라는 제목으로 자료가 공개되어 있습니다. 기본 아이디어는 EUC-KR이 한글 인코딩에 사용되는 것처럼 특정 인코딩은 특정 언어에만 많이 사용되므로, 각 언어의 패턴을 인식해서 인코딩을 찾아내는 것입니다.