Thursday, May 21, 2009

About Haskell (A Short Introduction to Haskell) 한글 번역 - 연재물을 순서대로 정렬하였습니다.

About Haskell
Haskell은 프로래밍언어의 하나입니다. 특히 다형성, 지연평가가 특징인 순수 함수형언어라는 점에서 다른 프로그래밍언어와 차이가 있습니다. 이 언어는 함수형언어의 기초가 되는 기호논리학에 업적을 세운 Haskell Brooks Curry의 이름을 따서 명명되었습니다. Haskell은 람다계산에 기초를 두고 있으며, 이것이 로고로도 활용되고 있습니다.



왜 Haskell은 사용하는가?
거대한 소프트웨어 시스템을 만드는 것은 매우 어렵고 비용이 듭니다. 이들 시스템을 유지하는 데는 더욱더 많은 노력과 돈이 들어갑니다. Haskell과 같은 함수형언어는 이러한 작업을 쉽고 저렴하게 할 수 있습니다.

순수 함수형언어인 Haskell은 아래와 같은 장점이 있습니다.

.실질적인 프로래머의 생산성의 향상.
.짧고 간결하고 보다 유지보수에 유리한 코드.
.적은 에러와 높은 신뢰성.
.프로그래머와 "의미의 갭"이 적은 언어.
.납기단축.

Haskell은 많은 종류의 application에 적합한 범용성이 높은 언어입니다. 특히 코드를 몇번이나 수정하거나 maintanence를 하는 프로그램에 적합합니다.

소프트웨어의 생산에서 많은 시간이 걸리는 과정은, 프로그램 사양의 결정, 디자인, 유지보수이며, application 자체인 것은 아니다. 함수형언어는 사양을 결정하는데 가장 뛰어나다. 그 사양은 사양인 동시에 실행가능한 프로그램이기도 하며, 최종결과로서의 프로그램 자체의 최초의 프로토타입이기도 하다.

동시에 함수형 프로그램은 코드가 짧고 간결하며, 엄격한 side effect의 제어에 의해서 예상할 수 없는 상호작용을 배제할 수 있기 때문에, 유지보수가 쉬워진다.



함수형언어란?
C, Java, Pascal, Ada등의 언어는 명령형 언어이다. 이들 언어는 순차적으로 실행되는 명령어들의 나열로 구성된다는 뜻에서 명령형이라고 불리고 있다.
Haskell은 함수형언어이다. 함수형 프로그램은 단 1개의 식으로부터 이루어지고, 이들을 평가(실행)함으로서 프로그램이 실행되게 된다. 스프레드쉬트를 사용해본 적이 있는 사람은 함수형언어를 경험해 보았다고 할 수 있다. 스프레드쉬트에서는 각 셀의 값을 다른 셀의 값을 기준으로 결정한다. 여기서 눈여겨 보아야 할 부분은, '무엇을 계산하는가'이며, '어떻게 계산하는가'가 아니다. 예를 들면,

.셀이 계산되는 순서는 지정되어있지 않다.-그 대신에 스프레드쉬트가 각각의 셀의 의존성에 대해서 계산해 줄것이라는 생각이 있다(함수형언어는 계산순서를 프로그래머가 결정하지 않고 무엇을 계산할 것인가만을 결정한다는 뜻으로 풀이됨)
.스프레드쉬트 소프트웨어가 메모리를 어떻게 사용하는지를 결정하지 않는다.-오히려 스프레드쉬트가 겉보기에는 무한한 셀이 있는 것으로 보이며, 메모리는 실제로 사용될 때 비로서 할당된다.
.거의 대부분의 경우, 각 셀의 값은, 그 값을 계산하기 위한 명령어의 나열이 아닌, 단 1개의 식으로 정해진다.

이 스프레드쉬트 소프트웨어에 있어서의 계산의 순서가 지정되지 않는 점에서, (변수에의) 대입이라는 개념이 그다지 도움이 되지 않는 다는 것이 흥미로운 점이다. 만약 대입이 언제 일어날지 모른다면, 대입을 유용하게 이용할 수 없다. 이러한 점은 기본적으로 대입문을 신중하게 나열해서 계산을 구성해가는 C언어나 메소드의 호출이 중요한 Java와 같은 관습적인 언어와는 비교가 된다.

저차원적인 '어떻게 (계산하는가?)'가 아닌 고차원적인 '무엇(을 계산하는가?)'에 촛점을 두는 것이 함수형언어가 다른 언어와 다른 가장 커다란 차이점이 된다.

다른 잘 알려진 함수형언어에 가까운 언어로는, 표준 데이터베이스 쿼리언어인 SQL인 있다. SQL의 쿼리는 투사, 선택, 결합등을 포함한 식이 된다. 쿼리는 어떤 관계가 계산될 것인가를 기술하며, 어떻게 계산할 것인가를 기술하지는 않는다. 물론 쿼리는 어떠한 순서로 평가(실행)이 되어도 상관이 없다. SQL이 장착된 소프트웨어의 대부분은 최대한 최적의 실행을 탐색하는 것으로 쿼리의 최적화를 이루어낸다.


함수형언어의 장점은?
스프레드쉬트나 SQL은 모두 특정 경우에만 사용하는 언어이다. 함수형언어는 같은 아이디어를 범용 프로그래밍의 영역에 적용한 것이다. 함수형 프로그램이 어떻한 것인지를 살펴보기 위해서, 아래에 퀵-정렬 프로그램을 예시한다. 이들 두 프로그램은 퀵-정렬이라는 방법을 사용해서 배열을 오름차순으로 정리하는 것이다. 첫 프로그램은 Hasekll로 작성하였으며, 두번째는 C로 작성하였다.

Haskell로 작성한 퀵-정렬

qsort [] = []
qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x
where
elts_lt_x = [y | y <- xs, y < elts_greq_x =" [y">= x]

C로 작성한 퀵-정렬

qsort( a, lo, hi ) int a[], hi, lo;
{
int h, l, p, t;

if (lo < l =" lo;" h =" hi;" p =" a[hi];" l =" l+1;"> l) && (a[h] >= p))
h = h-1;
if (l < t =" a[l];" t =" a[l];"> 연산자로 비교할 수 있는 요소를 가지는 어떠한 리스트도 정렬할 수 있습니다. 이에 반해 C언어의 경우에는 정수의 배열에만 한해서 사용할 수 있습니다.
다형성은 재이용성을 높여줍니다.

5. 강력한 지연평가
엄격하지 않은 함수형언어에는 답을 얻기 위해 필요한 만큼의 프로그램을 평가(실행)한다,는 강력한 특징이 있습니다. 이는 지연평가라고 불리웁니다. 이 특징은 Unix의 파이프에 비유될 수 있습니다. 예를 들면 Unix 명령어의

grep printf Foo.c | wc

는 Foo.c라는 파일 안의 printf라는 문자열을 포함하는 행의 수를 셉니다. "grep printf Foo.c"라는 명령어가 printf를 포함하는 모든 행을 표시해주는데 반해서, wc 명령어는 그 수를 셉니다. |는 파이프로서, 첫 명령어의 출력을 받아서 2번째의 프로그램으로 넘겨주는 역할을 합니다. 2번째 명령어는 동시에 실행되어서, 첫 명령어의 출력은 약간의 지연이 있기는 하여도, 그 직후에 사용되어 집니다. 이 방법에서는 크기가 큰 중간 파일을 만들 필요가 없습니다. wc는 grep에서 출력되는 행에 '의존하고 있다'라고 생각할 수 있습니다.

만일, 2번째 명력어가 첫 명령어의 출력의 일부만 사용한다고 하며, 첫 명령어는 (첫 명령어의 출력이) 끝까지 필요하지 않을 수 있습니다. 예를 들면,

grep printf Foo.c | head 5

는 printf가 포함되어 있는 행에서 첫 5개 행만을 표시합니다. grep의 실행을 중단해야 할지도 모르는 것을 고려한 프로그램으로 다시 작성할 필요가 없습니다.

엄격하지 않은 언어는 이와 같이 필요할 때만 평가하는 방법을 제공합니다.
명령어의 예에서 알 수 있듯이, 이는 기존의 프로그램을 짜기 위한 강력한 '지연성'을 제공합니다. 이는 명령형 프로그램을 작성하는 것보다, 프로그램의 재이용성이 높은 작은 프로그램으로 분할할 수 있다는 것을 나타냅니다. 지연평가에 의해서, 보다 모듈성이 높은 프로그램을 작성할 수 있습니다.

6. 강력한 추상화
일반적으로, 함수형언어는 추상화를 캡슐화하기 위한 강력한 새로운 기법을 가지고 있습니다. 추상화에 의해서 내부의 동작을 감추고 object를 정의하는 것이 가능해 졌습니다. 추상화는 모듈성이 높고 유지보수가 쉬운 프로그램을 구축하는데 있어서 핵심이 됩니다. 따라서, 새로운 언어에 대해서 '추상화를 위해 어떠한 메커니즘이 구현되어 있는가?'라는 것이 자주 문제가 됩니다.

함수형언어에 있어서 강력한 추상화 메커니즘으로는 고계함수가 있습니다. Haskell에서 함수는 first-class입니다. :함수는 다른 함수로 자유롭게 넘길수가 있으며, 함수의 되돌이값으로서 돌려줄 수도 있으며, 데이터 구조의 안에 수납할 수도 있습니다. 고계함수를 적절하게 사용함으로서 많은 프로그램의 구조나 모듈성을 향상시킬 수 있습니다.

7. 메모리 관리
많은 최신의 프로그램들은 힙 영역의 메모리를 자동적으로 확보해야만 합니다. C에서는 malloc을 통해서 이루어지고 있으며, 그 뒤로 그 영역을 초기화하는 코드가 이어집니다. 그 영역이 필요없게 되면 자유롭게 사용할 수 있는 메모리 풀로 되돌려주는 것은 프로그래며의 책임이며, 이것이 악명높은 dangling-pointer error의 근원이 됩니다. 더욱이 malloc은 상당히 화려한 함수로서, 프로그래머가 malloc을 통해서 커다란 덩어리를 확보하고, 그 안에서 '수동으로' 확보하는 경우도 자주 있습니다.

모든 함수형언어는 이러한 작업에서 프로그래머를 해방시킵니다. 메모리의 확보와 초기와는 암묵적인 상태에서 행해지며, 확보된 영역은 가베지 콜렉터에 의해서 자동적으로 회수됩니다. 이 기억영역의 확보와 가베지콜렉터의 기술은 현재 적절하게 성숙되어 있으며, 적은 코스트로 실행할 수 있습니다.

C가 나은 경우
물론 함수형언어가 모든 경우에 있어서 뛰어나다는 것은 아니다. C의 퀵-정렬은 Hoare에 의해서 고안된 배열을 치환하는 것으로 정렬을 수행하는, 매우 기교있는 기법을 사용하므로, 여분의 기억용량이 필요없다. 결과적으로, 적은 메모리를 사용하면서 빠르게 실행될 수 있다. 이와는 대조적으로 Haskell의 프로그램은 그 이면에서 여분의 메모리를 확보함으로, C보다 실행이 늦다.

즉, C의 퀵-정렬은 해독하기 어려운 대신에, 기억용량의 코스트를 줄이기 위해서 매우 기교적인 메모리관리를 실행하고 있다.

퍼포먼스가 중요시되는 응용프로그램이나, 저레벨의 알고리듬을 보다 세부적으로 조절해야하는 경우에는, 계산이 어떻게 실행되느냐보다는 세밀하게 제어되는 코드가 필요하므로, C언어와 같은 명령형언어가 Haskell을 선택하는 것 보다 낫다.


.함수형 VS 명령형

그러나 무엇보다도 퍼포먼스가 요구되는 프로그램이라는 것은 그다지 많지 않다. 무엇보다도, 옛날의 내부 루프를 남겨두고, 우리는 어셈블러로 프로그램을 만드는 것을 그만두었습니다. 보다 서포트성이 높은 프로그래밍 모델(임의로 명명되는 변수, 숫자가 정해져 있는 몇몇개의 레지스터 대신에 사용될 수 있는 지역변수)를 채용함으로서 얻어지는 이익은, 프로그램을 실행할 때의 코스트를 감안하더라도 매우 중요합니다.

마찬가지로, 가상 메모리 페이징 시스템도 널리 받아들여지고 있습니다. 무한의 가상 메모리 영역등 보다 좋은 서프트성이 높은 프로그래밍 모델을 만들 수 있습니다. 오늘날 명시적인 메모리 관리를 더 이상 수행되고 있지 않습니다.

함수형언어는 보다 높은 레벨의 프로그래밍 모델로 발돗음을 하려고 하고 있습니다. 프로그램은 보다 나은 디자인, 기술, 보수가 용이해 지고 있습니다만, 컴퓨터에서의 상세한 제어는 하지 못하게 되고 있습니다. 이점은 거의 모든 프로그램에 있어서 허용범위입니다.



Haskell이란 무엇인가?
Haskell은 근대적이며 표준적이면서 엄격하지 않은 순수한 함수형 프로그래밍언어입니다. 다형성, 지연평가, 고계함수등, 여러가지 특징을 모두 지니고 있습니다. 또한 오버로드체계적인 구성이나 모듈 시스템을 서포트하는 혁신적인 type 시스템을 가지고 있습니다.

표현력 있는 구문, 종래의 정수나 부동소수점, bool형에 더해서 임의정도의 정수나 유리수, 풍부한 제작가능 데이터형을 갖추고 있으며, 수치계산에서 추상적인 응용 프로그램까지 폭 넓게 서포트할 수 있도록 디자인되어 있습니다.



함수형 프로그램을 사용하고 있는 사람이 있습니까?
...번역 생략.



그 이외의 질문.
.함수형 프로그램을 배우기는 어렵습니까?
함수형 프로그래밍은 관점을 바꿔야만 가능하며, 이것을 어려워하는 프로그래머도 있습니다. 그러나, Erlang의 Ericsson에 의한 프로그래머의 트레이닝 실험에서는, 프로그래머가 하루아침에 되지 않을 것이라고 생각하고, 신중하게 트레이닝을 받으며, 많은 경우 이행은 쉽다고 합니다.

.함수형프로그램은 느리지 않습니까?
예전에는 그러하였지만, 현재는 컴파일러가 개선되었습니다. 퍼포먼스에 크게 의존하는 응용프로그램을 제외하면, 모든 Haskell 프로그램은 충분한 속도로 실행할 수 있습니다.

.C 또는 C++으로 쓰여진 대규모 응용프로그램이 이미 있습니다만, 시스템 전체를 다시 작성하지 않고 함수형언어의 장점을 도입할 수 있을까요?
Haskell은 기존의 응용프로그램에 여러가지 방법으로 잘 통합되어 왔습니다. HaskellDirect는 IDL(Interface Desciption Language)베이스의 툴로서, 이것에 의해서 Haskell 프로그램을 다른 소프트웨어 컴포넌트와 동시에 사용할 수 있습니다. C/C++에의 저레벨 인터페이스는 Green Card로 작성할 수 있습니다. 이것에 의해서 Haskell과 C의 강력한 통합이 가능합니다. 이들 툴을 사용해서 많은 다언어로부터 구축된 많은 시스템이 성공을 거두고 있습니다.

.Haskell이 서포트하고 있는 라이브러리에는 어떤 것이 있습니까?
많은 Haskell용의 소프트웨어 라이브러리가 개발되었습니다. List of Haskell Libraries (http://www.haskell.org/haskellwiki/Projects)에 이용가능한 라이브러리의 모든 리스트가 있습니다.

.그 이외의 Haskell용의 소프트웨어 툴에는 어떤 것이 있습니까?
Glasgow Haskell에서는 프로파일러를 이용할 수 있습니다. 이로 인해서 프로그램의 내부의 어느 부분이, 실행시간의 메모리스페이스의 대부분을 소비하고 있는지 알 수 있습니다. Chalmers Haskell은 스페이스 프로파일링 툴과, 프로그램을 병렬로 운직인 경우의 실험을 할 수 있는 quasi-paralell 시뮬레이션을 이용할 수 있습니다. Hug에서도 비슷한 툴이 이용가능합니다.

.서포트나 지원을 받을 수 있습니까?
아쉽게도 현 시점에서는 불가능합니다. Haskell은 어느 것이나 연구진에 의해서 만들어진 것이며, 이들이 기업과 계약을 맺음으로서, 시장에서의 찬스가 생길지도 모릅니다. 우일들은 이러한 것을 즐길 수 있는 사람과 같이 일할 수 있기를 기원하고 있습니다.

.어떻게 하면 Haskell을 배울 수 있습니까?
보다 많은 예나 설명은 Gentle Introduction to Haskell (http://www.haskell.org/tutorial/)을 참고해 주십시요. Haskell을 이용하기 위한 서적도 많이 있습니다. BookShelf (http://www.haskell.org/haskellwiki/Books)를 참고해 주십시요.

No comments: