[Haskell] 05. 리스트 타입 가지고 놀기 (1) – 리스트 연산

리스트 타입은 Haskel에서 가장 많이 쓰이는 타입이다. 여러가지 Type들을 담을 수 있는 일종의 Container이다.

Prelude> [1,2,3,4,5]
[1,2,3,4,5]
Prelude> :type [1,2,3,4,5]
[1,2,3,4,5] :: Num t => [t]

[1,2,3,4,5]의 타입을 확인해 보면, [Num]임을 알 수 있다. 즉 Num의 리스트 타입이다.

리스트를 입력으로 받는 몇 가지 함수들을 실행해 보자.

Prelude> head [1,2,3,4,5]
1
Prelude> tail [1,2,3,4,5]
[2,3,4,5]
Prelude> length [1,2,3,4,5]
5
Prelude> sum [1,2,3,4,5]
15
Prelude> product [1,2,3,4,5]
120
Prelude> reverse [1,2,3,4,5]
[5,4,3,2,1]

Prelude> take 3 [1,2,3,4,5]
[1,2,3]
Prelude> drop 3 [1,2,3,4,5]
[4,5]
  • head: 리스트의 맨 앞 원소를 반환
  • tail: 리스트의 맨 앞 원소를 제외한 리스트를 반환
  • length: 리스트의 길이
  • sum: 리스트 내의 숫자 합
  • product: 리스트 내의 숫자 곱
  • reverse: 리스트의 순서를 뒤집음
  • take n 리스트: 리스트의 앞 n개 원소를 갖는 리스트 반환
  • drop n 리스트: 리스트의 앞 n개 원소를 제외한 리스트 반환
Prelude> 1+3
4
Prelude> (+) 1 3
4
Prelude> 4*6
24
Prelude> (*) 4 6
24

앞에서 Interactive command line을 계산기처럼 이용할 수 있다고 하였다. 우리가 사용하는 연산자 +,-,*,/ 모두 사실은 함수다. 이를 함수 형태로 사용하기 위해서는 (+),(-),(*),(/)의 형태로 사용한다. 위의 예제에서 쉽게 확인할 수 있다. 이런 사칙연산 외에도 리스트에 적용할 수 있는 연산자들이 있다.

Prelude> [1,2,3,4,5] !! 2
3
Prelude> (!!) [1,2,3] 1
2

Prelude> [1,2,3,4] ++ [5,6,7,8]
[1,2,3,4,5,6,7,8]
Prelude> (++) [1,2,3] [4,5,6]
[1,2,3,4,5,6]

(!!) 연산자는 리스트에서 해당 인덱스의 값을 반환하는 연산자이다. 리스트의 인덱스는 0부터 시작한다. [1,2,3,4,5]의 경우 0번째가 1, 1번째 2, 2번째 3, … 그래서 [1,2,3,4,5] !! 2의 결과는 3이다. (!!) [1,2,3] 1의 형태로 사용할 수도 있다.
(++) 연산자는 2개의 리스트를 이어 주는 연산자이다. [1,2,3,4] ++ [5,6,7,8] 또는 (++) [1,2,3] [4,5,6]과 같은 형태로 사용할 수 있다.
리스트 안에 들어있는 원소는 반드시 모두 같은 타입이어야 한다.

마지막으로 map이라는 함수를 보자. map 함수는 리스트의 각 요소에 함수 \(f\)를 적용하고자 할 때 사용한다. 수학적으로는 아래와 같이 표현할 수도 있다.

\begin{equation}
[1,2,3,4,5,6] \mapsto [f(1),\ f(2),\ f(3),\ f(4),\ f(5),\ f(6)] \end{equation}

리스트 [1,-3,-5,2,7,-9]의 각 요소에 abs 함수를 적용하려 하면, abs([1,-3,-5,2,7,-9])를 하고 싶지만 abs 함수는 리스트를 입력으로 받지 않는다. 이 때 map 함수를 이용하여 우리가 원하는 결과 [1,3,5,2,7,9]를 얻을 수 있다.

Prelude> map abs [1,-3,-5,2,7,-9]
[1,3,5,2,7,9]

map 함수 리스트와 같은 형식으로 사용한다. 좀 더 다른 예를 보자. 각 요소에 모두 5를 더하고 싶다면 다음과 같이 할 수 있다.

Prelude> map (+5) [1,-3,-5,2,7,-9]
[6,2,0,7,12,-4]

놀랍도록 간단하지 않은가. (+5)가 5를 더한 값을 반환하는 함수인 것이다. 비슷한 형태의 다른 함수들도 있다.

Prelude> (+5) 3
8
Prelude> (*2) 7
14
Prelude> (/2) 8
4.0
Prelude> (1/) 4
0.25

이런 함수들은 map 함수를 사용할 때 매우 유용하게 쓰인다. 각 요소의 제곱을 반환하는 경우는 다음과 같이 사용할 수 있다.

Prelude> map (^2) [1,-3,-5,2,7,-9]
[1,9,25,4,49,81]

map과 비슷한 filter라는 함수도 있다. 함수 이름에서 짐작할 수 있듯이, 특정 조건을 기반으로 리스트의 요소들을 걸러내는 역할을 한다. filter 조건식 리스트의 형태로 사용한다.

Prelude> filter (>0) [1,-3,-5,2,7,-9]
[1,2,7]

Prelude> filter even [1,-3,-5,2,7,-9]
[2]

Prelude> filter prime [1,-3,-5,2,7,-9]
[2,7]

(>0)와 같은 함수를 사용해서 0보다 큰 요소들을 아주 빠르게 걸러낼 수 있다. even 함수를 이용해서 짝수만 걸러낼 수도 있으며, prime 함수를 이용하면 소수만 거를 수도 있다. (prime 함수는 다음 장에서 작성할 것이다.)

Reply