Haskell #3 (Baby’s first functions)

이번 장에서는 간단한 함수를 직접 만들어서 파일에 저장하고, REPL에서 함수를 로딩하여 실행하는 방법을 학습합니다.
Ref: #3. Starting Out- “Baby’s first functions”

baby.hs라는 파일 만들어 아래와 같이 입력한 후 저장합니다.

baby.hs

위에서 작성한 내용은 하스켈의 함수 입니다. doubleMe는 함수명이고 첫번째 x는 함수의 인자입니다. 함수를 호출할 때와 유사하게 space로 함수명과 인자를 구분합니다. =의 오른쪽은 함수가 할일을 정의하는 부분입니다.

작성한 파일을 로딩하여 사용해보았습니다. ghci에서 “:”은 명령 모드입니다. “:l” 명령을 통해서 작성된 hs 파일을 로딩할 수 있습니다. 로딩 후 해당 함수를 실행하면 곱하기 2가 동작하는 것을 확인할 수 있습니다.

위와같이 인자를 두개로 받는 함수를 정의해서 동작시켜 보았습니다. 다른 함수와의 조합도 간단히 수행해 봤습니다. (하스켈의 함수가 수학의 함수와 상당히 유사하게 생기지 않았나요?) 위에서 선언한 doubleUs 함수는 doubleMe 함수를 재사용하여 아래와 같이 선언하여 사용할 수도 있습니다.

이 예제는 매우 간단하지만 하스켈을 사용할 때 자주 쓰이는 패턴입니다. 기본적인 함수들을 만들고 함수들의 조합으로 복잡한 함수를 만들 수 있습니다. 이런 방식으로 불필요한 중복도 피할 수 있습니다. 만약 어떤 수학자가 doubleMe가 곱하기 2가 아니라 3인 것을 증명했다면, 간단히 doubleMe를 x + x + x로 수정하여 doubleUs까지 함께 해결할 수 있습니다.

하스켈에서 함수들은 특정한 순서가 없습니다. 따라서 doubleMe를 먼저 정의하고 doubleUs를 하거나 또는 다른 방식으로 해도 관계가 없습니다.

위와 같이 x가 100보다 작거나 같을때만 2를 곱하는 함수를 만들었습니다. 여기서 하스켈의 if문을 살펴볼 수 있습니다. 위의 예제를 보면 다른 명령형 언어와 다른 점은 else구문이 반드시 존재해야 한다는 점입니다. 명령형 언어에서는 else를 생략할 수 있었지만 하스켈에서는 모든 expression과 함수는 반드시 리턴을 해야합니다.

하스켈의 if문은 expression입니다. expression은 기본적으로 어떤 값을 리턴하는 코드 조각을 의미합니다. 예를들어 “5”는 “5”라는 값을 리턴하기 때문에 expression입니다. 4 + 8, x + y도 역시 값을 리턴하기 때문에 expression이라고 할 수 있습니다. 하스켈의 if문은 else가 생략될 수 없으므로, 항상 어떤 값을 리턴하기 때문에 expression 입니다. 만약에 doubleSmallNumber의 모든 결과값에 1을 더하고 싶다면 아래와 같이 수정할 수 있습니다.

여기서 괄호를 생략하면 x가 100보다 클때만 1을 더하게 될 것 입니다. 여기서 함수명 뒤에 ‘(apostrophe)가 있는 것을 볼 수 있습니다. 하스켈에서는 함수명에 ‘를 사용할 수 있습니다. 함수명에 ‘를 쓰는 경우는 게으르지 않은 함수(isn’t lazy)나 함수 또는 변수가 약간 수정된 버전등을 표시할 때 사용됩니다. 함수명에서 ‘가 허용되는 문자이기 때문에 아래와 같은 함수를 만들 수도 있습니다.

이 예제에서도 두가지 알아야할 특성들이 있습니다. 먼저 함수 이름의 첫번째 글자가 대문자가 아니라는 점입니다. 하스켈에서는 함수의 첫번째 글자로 대문자를 허용하지 않습니다. 이 부분은 나중에 다시 살펴보겠습니다. 두번째는 어떤 인자도 없다는 점입니다. 함수가 어떤 인자도 받지 않을때, definition(or a name)이라고 말합니다. 그 이유는 이름들이 가리키는 것을 한번 정의하면 바꿀 수 없기때문입니다. (상수를 설명하는 것으로 보입니다.)