Haskell #8 (Believe the type)

이번 장부터는 새로운 챕터가 시작됩니다. 언어를 이해하고 제대로 사용하는 상당히 중요한 부분을 차지하는 타입 시스템에 대한 내용을 다루는 부분입니다. 처음 하스켈을 소개할 때 “정적 타입 시스템을 가지고 있다”라고 언급 했었는데, 이번 챕터에서 자세히 알아볼 것 입니다.
Ref: Types and Typeclasses-Believe the type

하스켈은 정적 타입시스템을 사용합니다. 하스켈에서 모든 표현식(expression)의 타입은 컴파일 타임에 결정됩니다. 만약 코드 작성에 오류를 범하면 컴파일이 되지 않기때문에 좀 더 안전한 코드를 작성하는데 도움이 됩니다. 이것은 실행 타임에 크래쉬가 발생할 확률을 줄여주기도 합니다. 하스켈의 모든 것은 타입을 가지고 있기때문에 컴파일러는 컴파일전에 프로그램에 대한 매우 많은 것을 미리 알 수 있습니다.

자바나 파스칼과는 달리, 하스켈은 타입 추론을 합니다. 만약 숫자를 쓰는 중이라면 숫자라고 알려줄 필요가 없습니다. 스스로 추론할 수 있기 때문에 함수나 표현식의 타입을 명시적을 쓸 필요가 없습니다. 여기까지 하스켈의 타입 시스템에 대해서 아주 간단하게 알아봤지만, 하스켈을 배우는데 있어서 타입 시스템을 이해하는 것은 매우 중요합니다.

타입은 모든 표현식(expression)이 가지는 라벨과 같습니다. 타입은 표현식이 어떤 범주에 맞는지를 알려줍니다. (True는 boolean, “Hello”는 문자열 등)

지금부터 GHCI에서 :t 명령어를 사용해서 몇가지 올바른 표현식(expression)에 타입을 검사해보겠습니다.

:t 명령어를 사용하면 해당 표현식에 ::(has type of)를 붙여서 타입을 알려주는 것을 알 수 있습니다. 타입은 항상 첫글자가 대문자 입니다. 이 예제에서 눈여서 살펴볼 것은 “Hello”가 [Char]와 같이 문자의 리스트 타입을 되어있다는 것입니다. 리스트와는 다르게 튜플은 각 길이에 따라서 다른 타입을 가지는 것을 볼 수 있는데, 아래 예제를 보면 좀 더 쉽게 이해할 수 있을 것입니다.

함수들도 타입을 가집니다. 우리가 함수를 작성할 때는 명시적으로 타입 선언을 선택할 수 있습니다. 일반적으로 함수를 작성할 때는 매우 짧은 함수를 제외하고는 타입 선언을 명시하는 것이 좋습니다.

문자 리스트를 입력받아서 대문자만 남기고 모두 제거하는 문자 리스트를 반환하는 함수 입니다. 여기서 removeNonUppercase 함수는 [Char] -> [Char] 타입을 가지고, 문자열을 입력 받아서 문자열을 리턴한다는 의미입니다. 여기서 [Char]은 문자열과 동일하기때문에 removeNonUppercase :: String -> String으로 선언할 수도 있습니다.

함수를 선언할때도 컴파일러가 추론이 가능하기 때문에 타입을 명시하지 않아도 됩니다. 하지만, 위 예제에서는 타입을 선언했습니다. 만약 여러개의 파라메터를 받는 함수를 선언한다면 어떻게 할까요?

이 예제는 세개의 파라메터를 받아서 모두 더하는 함수 입니다. 다른 구분자 없이 ->로 파라메터를 구분하고 마지막에 리턴 타입을 적었습니다. 뒤에서 왜 리턴 타입과 파라메터를 구분하기 위해서 별도의 구분자를 사용하지 않아도 되는지 배울 것 입니다.

아래는 하스켈에서 사용하는 몇몇 공통 타입에 대한 설명입니다.

  • Int는 integer를 나타냅니다. Int는 모든 숫자들에 사용됩니다. Int는 32bit 머신에서 보통 -2147483648 ~ 2147483647의 범위를 가집니다.
  • Integer도 역시 integer를 나타냅니다. Int와의 차이점은 범위가 없다는 점이고, 매우 매우 큰 수를 표현할 때 사용됩니다. 하지만 Int에 비해서 비효율적으로 동작합니다.
  • Float는 단일 정밀도를 가지는 부동 소수점입니다.
  • Double는 두배의 정확성을 가지는 부동 소수점 입니다.
  • Bool은 boolean 타입니다. True와 False만 가질 수 있습니다.
  • Char은 문자를 나타냅니다. ‘’로 표현할 수 있고, 문자의 리스트는 문자열 입니다.
  • 튜플의 경우, 튜플내의 원소의 개수와 각 원소의 타입에 따라서 튜플의 타입이 전부 달라지기 때문에 무한대의 타입을 가진다고 볼 수 있습니다. 튜플은 ()로 표현할 수 있습니다.