프로그래밍 언어는 결국 컴퓨터 상에서 실행되는 프로그램을 생성하기 위한 도구다. 가장 근본적이자 원시적인 언어는 기계어이고, 기계어의 거의 일대일 대응 격인 어셈블리어가 그 다음이다. 2학년 수업 중에 <컴퓨터 구조>에서 배우듯이 프로그램의 실행은 일련의 명령(instruction)을 클럭이 박동함에 따라 인출, 판독, 실행하는 과정이다. 즉 태생이 절차적(procedural)일 수 밖에 없다. 어셈블리어에서는 프로그램에서 쓰이는 모든 데이터를 단순히 데이터 영역에 주루룩 나열한다면, 이제 C에서는 여러 데이터를 하나로 묶어 구조체로 만드는 구조적(structural) 프로그래밍을 지원한다. 그 구조체들 사이의 상하, 대응, 포함 관계나 상호작용하는 방법을 다루는 객체지향(object-oriented)이라는 개념이 등장하였고 C++, 자바 같은 주류 언어에서 문법적으로 지원하고 있다. 하지만 이들 언어로 작성한 코드는 다음과 같은 일반적인 개념이 성립한다. 1. 코드의 각각의 줄이 하나의 명령문(statement)이 된다. 2. 한 번에 한 명령문을 실행하고 그 다음에 어떤 명령문을 실행할 지가 결정된다. 즉 프로그램의 원시적인 작동 방식이 여전히 코드 상에 반영되어 있는 것이다. 한 명령을 실행하고, 프로그램 카운터는 다음에 실행할 명령을 찾고, 그 명령문은 다음 클럭에 실행하고... 이걸 추상적인 수준으로 끌어올렸을 뿐 코드에 그 절차가 고스란히 묻어있는 것이다. 함수형(functional) 언어인 하스켈은 완전히 다른 방식으로 프로그램에 접근한다. 명령 인출-판독-실행은 잊어라. 흐름 제어도 잊어라. 문제를 푸는 데 필요한 정의들을 적어라. 그리고 그 정의에서 필요한 부분만 실행하라. 명령형(imperative) 언어에서는 추상적인 논리를 코드로 실행 가능한 절차로 표현한다면 하스켈에서는 코드로 논리를 그대로 표현하고 컴파일러가 그걸 알아서 실현 가능한 프로그램으로 만들어낸다. 하스켈 코드 한 줄은 '''기계에 종속적인''' 절차와 일대일 대응이 되지 않는다. C 같은 언어로 프로그래밍을 처음 배울 때면 x = x+1 은 "x와 x+1가 같다"가 아니라 x에 x+1을 할당하는(assign) 거라고 배운다. 하스켈에서는 정말로 x = x+1 이라고 정의해버린다. (하지만 x를 실제로 쓰기 전에는 프로그램이 무한 루프에 빠지지는 않는데 이는 하스켈의 지연 평가(lazy evaluation)라는 특성과 관련이 있다. 자세한 건 검색) 또한 하스켈의 주요 특징 중 하나는 순수성인데, 함수 내에서 부수효과(side-effect)를 일으킬 수 없다는 것이다. 함수의 출력이 달라지는 요인은 오직 그 함수에 입력되는 인자 뿐이다. 인자가 같으면 무조건 출력도 같다. 어떤 함수 내에서 데이터에 가하는 어떤 수정도 다른 함수의 실행에 영향을 끼칠 수 없다. (그러기 위해서는 데이터를 항상 복사해야 하는데 자연스레 수행능력 면에서는 C++ 같은 언어보다 뒤쳐질 수 밖에 없다) 하스켈 코드가 읽기 힘든 것은 특유의 압축성 때문이다. 사실 풀어쓰면 그다지 어려울 것 없는 코드를, 단순한 연산들을 정체불명의 함수들(id, const, map, fold, zip, ($), (.), (>>=) 등)로 감싸고 한 줄에 모조리 때려박으면 이제 타 언어 사용자가 알아볼 수 없는 괴이한 코드가 된다. C나 자바가 구구단이라면 하스켈은 19단은 외워야 걸음마를 뗄 수 있는 것 같다. '''예시 1''' {{{ import Data.Bits import Numeric -- 32비트 정수를 8비트씩 잘라낸다 split :: Int -> [Int] split n = [b1, b2, b3, b4] where b1 = n .&. 0xFF b2 = (n `shiftR` 8) .&. 0xFF b3 = (n `shiftR` 16) .&. 0xFF b4 = (n `shiftR` 24) .&. 0xFF main = print $ map showHex (split 0x12345678) -- ["12","34","56","78"] 출력 }}} 하스켈 코드를 본 적이 없어도 split 함수를 대충은 알아볼 수 있다. 이제 한 줄로 압축해보자. {{{ split n = map (.&. 0xFF) (zipWith shiftR [n,n,n,n] [24,16..]) }}} ??????????????????????????????????????????????????????? '''예시 2''' - 리스트의 짝수 번째 원소들에만 2 곱하기 {{{ xs = [1, 10, 2, 20, 3, 30, 4, 40] xs' = zipWith ($) (cycle [(*2), id]) xs -- 뭐라고요 main = print xs >> print xs' -- 출력 [1,10,2,20,3,30,4,40] [2,10,4,20,6,30,8,40] }}} '''예시 3''' - [https://algospot.com/judge/problem/read/LECTURE] 의 해답 {{{ import System.IO import Data.List import Control.Monad -- 알아볼 수 없는 모나드의 향연 main = getLine >>= (\ n -> replicateM_ (read n :: Int) solve) solve = getLine >>= (\ str -> putStrLn $ (concat . sort . pairup) str) pairup str = sub [] str where sub xs [] = xs sub xs ys = sub ((2 `take` ys) : xs) (2 `drop` ys) }}} ---- * 하스켈에 대한 전반적인 설명은 위키피디아 참조 * 한글: [http://ko.wikipedia.org/wiki/%ED%95%98%EC%8A%A4%EC%BC%88] * 영어: [http://en.wikipedia.org/wiki/Haskell_(programming_language)] *하스켈 공부 자료를 찾는다면 다음 사이트를 추천합니다. 여러 링크가 잘 정리되어 있습니다. * [https://sites.google.com/site/pieceofhaskell/] * 제로위키 내에는 하스켈 관련 기존 페이지가 2개 밖에 없네요.. * [http://wiki.zeropage.org/wiki.php/BeginningHaskellLanguage] * [http://wiki.zeropage.org/wiki.php/HaskellLanguage] * 온라인 자료 * 위키피디아의 하스켈 위키책 [http://en.wikibooks.org/wiki/Haskell] * 참고로 위키책은 제가 번역하고 있어요.. [https://wikidocs.net/book/204] - [이민석] * Real World Haskell [http://book.realworldhaskell.org/] * 위키책의 코드는 문법 설명을 위한 인위적인 예제들 * 여러 라이브러리를 활용하는 법에 대한 실전 코드 제공(파일 I/O, 네트워크, GUI, 데이터베이스...) * 각 분야에 대한 사전 지식은 필요 * 파일 I/O: 파일 핸들, 읽기/쓰기 모드, 파일 및 디렉토리 체계 * 데이터베이스: 쿼리 구문, 데이터베이의 구조 * 사실 실전 경험이 없다면 예제 코드를 읽기가 상당히 벅찰 것 * 하지만 있다면! 코드만 읽어도 라이브러리 사용법을 대강 파악할 수 있음 * 관련 지식을 일일이 설명했으면 책이 너무 길어졌을 것. 분량 면에서 적당한 벌충안 * Parallel and Concurrent Programming in Haskell [http://chimera.labs.oreilly.com/books/1230000000929/index.html] * 스탠포드 대학 강의노트(CS240h: Functional Systems in Haskell) [http://www.scs.stanford.edu/11au-cs240h/] * What I Wish I Knew When Learning Haskell 2.1 [http://dev.stephendiehl.com/hask/] ---- * 한글로 된 하스켈 책이 두 개 있는 것 같은데 혹시 둘 다 별로였나? - [서민관] - [http://www.yes24.com/24/goods/3479645?scode=032&OzSrank=2], - [http://www.yes24.com/24/goods/12155304?scode=032&OzSrank=1] - 하스켈 공부를 군대에서 시작해서 볼 수가 없었어요.. 예전에 학교 도서관에서 둘 중 하나를 본 적은 있습니다. 무엇보다 http://book.realworldhaskell.org/ 이게 내용이 좋습니다. 위키책은 솔직히 문법 배우는 것 이상의 의미는 없고 실용 서적으로는 최고인 것 같네요. - 이민석 * 첫 번째는 2번씩이나 읽었지만 설명이 친절했다고 말하기 힘드네요. :( - 이원준