[Haskell] 04. 기본 입출력 타입(Type)

지금까지는 함수를 주로 다루었다. 함수(Function)란?에서 보았던 함수 표현식을 다시 보자.

\begin{align}
x \mapsto x^2, \quad x \in \mathbb{Z} \quad \text{(1)}\\
x \mapsto 2x+3,\quad x \in \mathbb{N} \quad \text{(2)} \\
x \mapsto x^3+3x+5,\quad x \in \mathbb{R} \quad \text{(3)}
\end{align}

이제 입출력 값의 형태(Type)에 대해 살펴 보려고 한다. 위의 함수들을 보면 \(x\)값의 범위가 정해져있다. 우리말로는 정의역이라 하고, 영어로는 domain이라고 한다. 이런! 영어가 더 쉽다. 함수 (1)에서는 \(x\)는 정수(Integer)의 범위를 갖는다. \(x=0.1\) 또는 \(x\)=”asdf” 이런거 입력으로 받지 않는다는 표현이다. 함수 (2)에서는 자연수(natural number)만 입력으로 받는다. 함수 (3)은 모든 실수(real number)를 입력으로 받는다. 이런 방법으로 수학에서는 \(x \in \mathbb{R}\)이라는 표현으로 입력값을 제한한다. 일반적으로 프로그래밍 언어에서는 Type이라는 표현으로 이를 제한한다.

double square(double x) { // C, C++ code
    return x*x;
}

이 함수는 double형의 입력을 받아 double형의 출력값을 반환한다. CC++에서는 명시적으로 변수의 타입을 선언해 주어야 한다. Python 같은 경우는 Type에 대한 선언 없이 바로 변수를 사용할 수도 있다. Haskell에서의 기본 변수 타입을 보자.

Prelude> let a = 5
Prelude> let b = 2.3
Prelude> let c = "asdf"
Prelude> let d = 'a'
Prelude> let e = True
Prelude> let f = [1,2,3,4,5]
Prelude> let g = (2, "abc")

Prelude> a
5
Prelude> b
2.3
Prelude> c
"asdf"
Prelude> d
'a'
Prelude> e
True
Prelude> f
[1,2,3,4,5]
Prelude> g
(2,"abc")

Prelude> :type a
a :: Num a => a
Prelude> :type b
b :: Fractional a => a
Prelude> :type c
c :: [Char]
Prelude> :type d
d :: Char
Prelude> :t e
e :: Bool
Prelude> :t f
f :: Num t => [t]
Prelude> :t g
g :: Num t => (t, [Char])

Haskell에서는 명시적으로 Type을 선언해 주지 않아도, 알아서 유추(Infer)한다. 위의 예제에서는 a,b,c,d,e,f,g 7개의 변수를 선언했다. Interactive command line에서 변수의 type을 볼 수 있는 명령은 :type 변수명이다. 또는 간단히 :t 변수명으로 조회할 수 있다.

  • a는 Num 타입,
  • b는 Fractional 타입,
  • c는 Char의 리스트 타입,
  • d는 Char 타입,
  • e는 Bool 타입,
  • f는 Num의 리스트 타입,
  • g는 (Num, [Char])인 Tuple 타입이다.

Num 타입은 Int, Integer, Float, Double 타입을 가르킨다. Fractional 타입은 Doulbe, Float 타입을 가르키고, Int, Integer 타입을 가르키는 Integral 타입도 있다. True, False를 나타내는 Bool 타입이 있고, “asdf” 같은 String[Char]로 나타낸다. 여기서 [ ] 기호는 리스트 타입을 나타낸다.

여기서 중요한 점은 모든 변수 이름과 함수 이름은 소문자로 시작해야 한다는 점이다. 타입명만 대문자로 시작할 수 있다.

아래와 같이 명시적으로 타입을 정해줄 수도 있다.

Prelude> let h = 4 :: Int
Prelude> let k = 5 :: Integer
Prelude> let l = 6 :: Float
Prelude> let m = "asdf" :: String

Prelude> h
4
Prelude> k
5
Prelude> l
6.0
Prelude> m
"asdf"

Prelude> :type h
h :: Int
Prelude> :type k
k :: Integer
Prelude> :type l
l :: Float
Prelude> :type m
m :: String

IntInteger의 차이는 표현할 수 있는 자리 수의 차이이다. Int는 -9223372036854775808 ~ 9223372036854775807의 범위를 갖는 Integer이고, Integer는 메모리가 허용하는 한 무한대의 자리 수를 표현할 수 있다.

Reply