Haskell #7 (Tuples)

--

이번 장에서는 하스켈의 튜플이라는 자료구조에 대해서 알아봅니다.

Ref: #6. Starting out-”Tuples”

튜플은 하나의 값에 여러개의 값들을 포함하는 방법이라는 측면에서 리스트와 유사합니다. 하지만 몇가지 근본적인 차이가 있습니다.

  • 리스트는 숫자들의 리스트라면 그 자체로 타입이고, 숫자들이 한개이 있든 무한개가 있든 상관하지 않습니다. 하지만 튜플은 몇개의 값으로 구성할지 정확하게 알고 있을때 사용됩니다. 또한 튜플의 타입은 구성값의 개수와 타입에 의해서 결정됩니다.
  • 튜플은 리스트와 다르게 여러가지의 타입의 조합을 포함하는 것이 가능합니다.

하스켈에서 2차원 벡터를 표현하는 예제로 차이점을 확인해 보겠습니다. 아래는 평면위에 다수의 점으로 모양을 표현하기 위한 리스트 입니다.

리스트에서는 값의 개수에 관계없이 리스트 타입이기때문에 값의 개수가 다른 리스트들이 같이 들어가도 문제가 없습니다. 하지만 숫자 3개로 평면위의 점을 표현하는 것은 이상합니다.

하스켈에서 튜플은 [] 대신 ()로 표현합니다. 튜플에서는 숫자가 2개인 튜플이 3개인 튜플과 다른 타입이기 때문에 에러가 발생하는 것을 보실 수 있습니다. 이처럼 튜플에서는 2개의 숫자로 구성된 점을 하나의 타입으로 생각할 수 있습니다.

마찬가지로 튜플은 구성 값들의 타입에 따라서 튜플의 타입이 달라지기 때문에 에러가 발생하는 것을 보실 수 있습니다. 이런 특성으로 튜플은 다양한 데이터를 표현할 수 있게 됩니다. 예를들어 누군가의 이름과 나이를 표현할때 튜플을 사용할 수 있습니다 (“Christopher”, “Walken”, 55). 또한 튜플은 리스트를 포함하는 것도 가능합니다.

어떤 데이터가 포함하는 구성값들의 개수와 타입을 알고 있다면 튜플을 사용합니다. 튜플을 이렇게 구성요소의 개수나 타입에 따라서 엄격하기 때문에 일반적인 함수를 사용해서 값을 추가할 수 없습니다. 값의 크기에 따라서 튜플에 추가하기 위한 함수를 직접 작성해주어야 합니다.

싱글톤 리스트들은 있지만 싱글톤 튜플같은 것은 없습니다. 싱글톤 튜플은 포함하고 있는 값 그 자체이기 때문에 튜플을 그냥 쓰는 것에 비해서 어떤 이점도 없습니다. (?정확히 이해 못함 ㅜㅜ)

튜플로 리스트처럼 튜플간에 비교가 가능합니다. 하지만 두 개의 튜플의 크기가 동일할 때만 비교가 가능합니다.

  • fst : 두개의 값(pair)을 가져와서 첫번째 값을 리턴합니다.
  • snd : 두개의 값(pair)을 가져와서 두번째 값을 리턴합니다.

여기서 fst 함수와 snd 함수는 튜플에 두개의 값(pair)이 있는 경우에만 동작합니다.

  • zip : 두개의 리스트를 가져와서 각 리스트의 값을 1개씩 꺼내고 합쳐서 튜플을 만듭니다. 첫번째 값을 첫번째끼리 묶고, 두번째 값을 두번째 값끼리 묶습니다. 이렇게 만들어진 튜플들의 리스트를 만들어서 리턴합니다.

zip은 간단한 함수지만, 쓰임새가 많습니다. 특히 두개의 리스트를 하나로 합치거나, 두개의 리스트를 동시에 순회할때 사용됩니다. zip 예제를 좀 더 살펴 보겠습니다.

zip은 서로 다른 타입의 값을 포함한 두 개의 리스트를 합칠 수도 있습니다.

위와 같이 길이가 다른 리스트 두개를 합치는 것도 가능합니다. 앞에서 부터 매칭이 가능한 값들이 새로운 리스트에 합쳐지고, 길이가 긴 리스트의 나머지 값들을 짤립니다.

무한대의 리스트를 가지고 zip을 해도 동일하게 짧은 리스트를 기준으로 병합됩니다.

지금까지 배운 튜플들의 조합과 리스트의 정의(comprehension)로 문제를 하나 풀어보겠습니다. 모든 변의 길이가 10이하의 정수인 직각 삼각형이 있습니다. 삼각형의 둘레는 24입니다. 먼저 모든 변의 길이가 10이하의 정수인 직각 삼각형을 만들면 아래와 같습니다.

세개의 리스트로 10이하의 정수인 변을 정의하고, 세개의 변을 조합하여 함수를 만들었습니다.

triangles 함수를 실행해보면 위와 같이 세변의 모두 길이가 10보다 작은 모든 삼각형들의 리스트가 리턴됩니다.(지면 관계상 출력의 일부만 캡쳐함.) 이제 여기에 직각 삼각형만 출력되도록 조건을 추가하겠습니다. 또한, 변 b는 빗변 c보다 작고, 변 a는 변 b보다 길이가 짧습니다. (그림 그대로..)

이제 마지막으로 직각 삼각형의 둘레가 24인 것만 출력하도록 하겠습니다.

이제 답을 얻었습니다. 여기서 풀어본 방식이 함수형 프로그래밍의 기본 패턴입니다. 먼저 답을 구하기 위한 초기 셋을 얻은 후에 답에 가깝게 변환하고, 필터링하면서 최종 정답을 찾아갑니다.

--

--