김재우 [email protected]

블루엣 인터내셔널의 기술 이사로 재직중이며 개발 환경과 온라인 교육 시스템을 결합한 소프트웨어를 설계하고 있다. 소프트웨어 공학 기술이나 관련 이론을 실천하도록 만드는 것이 개발자로서의 목표. 현재 정보기술원과 함께 분야별 표준 교육 과정. 전문 개발자 양성 및 인증을 위한 교육 시스템‘Theory Into Practice’를 설계하고 있다.

Haskell만의 독특하고 아름다운 기능을 소개한다. Haskell을 통해 그 동안 프로그래밍 분야에서 어떤 노력이 있었고, 그 결과 어떤 성과를 이뤘는지 살펴볼 수 있는 좋은 계기가 될 것이다.

지난 호에 이어 이번에도 Haskell의 뛰어난 표현력을 살펴볼 것이다. 물론 지금까지 소개한 기능만으로도 Haskell이 시중의 다른 언어와 어떻게 다른지 충분히 알 수 있다. 하지만 비슷한 표현 수단을 공유하는 언어(Miranda, ML, 파이썬, Clean 등)도 많기 때문에 Haskell만의 고유한 특징을 보여줬다고 할 수 없다. 그래서 이번에는 Haskell이 Haskell이라 불리는 이유에 해당하는 기능을 소재로 삼아 나머지 얘기를 이어가고자 한다.

이번에 다룰 Haskell 기능 중 형 클래스(Type class)와 모나드(Monad), 이 두 기법은 아주 독창성이 뛰어난 성과물이다. 그저 한 언어의 고유한 기능이라기보다 그동안 축적된 프로그래밍 분야의 연구 성과를 알차게 반영한 결과라 할 수 있다. 따라서 다른 프로그래밍 방식에 능통한 사람이라 해도 눈여겨봐야 할 만한 가치가 충분하다.

특히 객체지향성의 거품(?) 속을 헤매던 사람이라면 형 클래스 기능을 공부하면서 ‘클래스(Class)’란 단어의 참뜻을 새롭게 할 계기가 될 것이고, 형의 본질에 다가가는 기능을 맛볼 수 있을 것이다. 서브타이핑의 효과를 맹신하고 있었던 프로그래머라면 ‘덮어쓰기(overriding)’로 동적 결합을 허용하는 방식만이 점진 비파괴 확장(Incremental nondestructive extension)의 유일한 답이 아니라는 점도 깨닫게 될 것이다.

또한 모나드는 기존 기계식 프로그래밍(Imperative Programming)을 다른 시각에서 다른 가치로 새롭게 비추어 볼 수 있도록 시야를 넓혀 줄 것이고, ‘시간에 따른 상태 변화(State-oriented history-sensitive computation)’를 계산에 이용하는 것이 유리한 경우라 할지라도(폰 노이만 식 하드웨어 구조로부터 내려받은 배정문(Assignment)이 없어도), 순수함을 지켜가며 상태 변화를 표현하는 새로운 기법을 경험하게 될 것이다.

Arity로부터의 자유, 커링

지금까지 Haskell 코드를 세심하게 살펴본 독자라면 함수를 정의하는 문법이 좀 유별나다는 점을 눈치 챘을 것이다.예를 들어 다른 언어라면 f(x, y, z)라고 쓸 것을 Haskell에서는 다음과 같은 문법을 쓴다.

f x y z = x + y + z

함수 이름과 인자를 구분하기 위해 묶어두는 괄호도 없고, 인자 사이를 구분하는 쉼표도 없다. 언뜻 별 차이도 없어 보이는데, 왜 익숙한 문법을 놔두고 이런 표현을 강요하는 것일까? 물론 그 까닭을 모른다고 해도 코드를 쓰는 데는 아무런 지장이 없지만, 그 뒤에 숨은 깊은 뜻과 이론의 배경을 알아두면 프로그래밍이 한층 즐겁고, 문법의 유연함에서 오는 표현의 자유를 만끽할 수 있다.

Haskell 문법에서는 맨 앞에 나오는 이름이 저절로 함수의 이름이 되고, 뒤에 오는 것을 인자의 이름으로 취급한다. 그리고 각 인자는공백문자로구분한다. 이때 우리는 보통 함수 f가 세 개의 인자 x y z를 모조리 건네주는 것으로 해석하지만, Haskell에서는 함수를 그렇게 다루지 않는다. Haskell의 모든 함수는 인자를 하나만 받아들이는 단항 연산이다. 함수 f는 그저 x 하나만 받아들이는 함수이며, yz는 차례로 그 결과 값(함수)에 적용된다. 즉 앞에서 함수 f의 정의는 다음과 같은 람다(Lambda) 식의 약식 표현이다.

f = (\\x -> (y -> (\\z -> x + y + z)))