계정: 로그인
AA 📝
12. 타입의 함정들

A Gentle Introduction to Haskell, Version 98
이전 다음 위로


이 짧막한 장에서는 초보자가 Haskell의 타입 시스템을 사용하면서 빠져들게 되는 몇가지 일반적인 문제점들에 대한 직관적인 설명을 해봅니다.

12.1 Let-Bound Polymorphism

Hindley-Milner 타입 시스템을 사용하는 모든 언어들에는 let-bound polymorphism이라고 불리는 것이 있으며, 이는 let 절이나 where 절을 사용해서 (혹은 모듈의 최상위 수준에서) 바인드되지 않은 indentifier들은 그들의 polymorphism 측면에서 제한을 받기 때문입니다. 특히, λ-bound 함수(즉, 다른 함수에 인수로서 전달되는 함수)는 두 가지 다른 방식으로 초기화될 수 없습니다. 예를 들어, 다음과 같은 프로그램은 적법하지 않으며:

   1 let f g = (g [], g 'a')     -- ill-typed expression
   2 in f (\x->x)

이는 최우선 타입이 aa인 λ abstraction에 바인드된 gf 내부에서 두 가지 다른 방식으로 사용되기 때문입니다: 한번은 [a][a] 타입으로, 또 한 번은 CharChar 타입으로 사용되고 있죠.

12.2 수치 오버로딩

수치들이 오버로드되어있다는 사실과, 다른 많은 언어들에서와는 달리 다양한 수치형으로 암묵적으로 변환되지는 않는다는 사실은 때때로 잊혀지기 쉽습니다. 더욱 일반적인 수치 표현식들도 때로는 그다지 일반적이지 않을 수 있습니다. 흔히 일어나는 수치형 타입 오류 중 하나는 다음과 같은 경우입니다:

   1 average xs    =  sum xs / length xs     -- Wrong!

(/)는 소수 인수를 요구하는데 length의 결과는 Int 타입입니다. 이런 타입 불일치는 명시적인 강제 형변환을 통해 해결해야합니다:

   1 average       :: (Fractional a) => [a] -> a
   2 average xs    =  sum xs / fromIntegral (length xs)

12.3 The Monomorphism Restriction

Haskell의 타입 시스템에는 타입 클래스에 관해서 평범한 Hindley-Milner 타입 시스템에서는 찾아볼 수 없는 제한이 하나 있는데, 바로 monomorphism restriction입니다. 이 제한의 원인은 타입 상의 미묘한 모호함에 있으며, Haskell Report (§4.5.5)에서 자세히 설명하고 있습니다. 이것을 좀 더 간단히 설명하자면:

Monomorphism restriction의 의미는 (단일 indentifier에 대한 바인딩을 포함하는) 패턴 바인딩에 의해 바인드되고 명시적인 타입 지정자를 갖지 않는 모든 identifier들은 monomorphic해야 한다는 것입니다. Identifier는 만일 오버로드되어있지 않거나, 오버로드되어있다고 해도 최소한 하나 이상의 특정 오버로딩에 사용되고 있고 수출되지는 않았다면 monomorphic합니다.

이런 제한을 어기면 static type error가 발생합니다. 이 문제를 피해가는 가장 단순한 방법은 명시적으로 타입 지정자를 지정해주는 것입니다. (그것이 타입으로서 옳바르기만 하다면—‘type correct’) 어떠한 타입 지정자라도 모두 제대로 작동합니다.

아래에 보이는 Standard Prelude의 sum 정의에서처럼, 제한에 위배되는 일은 higher-order 방식으로 정의된 함수에서 흔히 발생합니다:

   1 sum    =  foldl (+) 0

이것은 static type error를 유발합니다. 여기에 타입 지정자를 붙여서 문제를 해결할 수 있습니다:

   1 sum    :: (Num a) => [a] -> a

만일 다음과 같이 썼더라면 문제가 발생하지 않았을 것이며:

   1 sum xs    =  foldl (+) 0 xs

이 제한이라는 것이 패턴 바인딩에만 적용되기 때문입니다.


이전 다음 위로
A Gentle Introduction to Haskell, Version 98

Copyright © 1999 Paul Hudak, John Peterson and Joseph Fasel

Permission is hereby granted, free of charge, to any person obtaining a copy of “A Gentle Introduction to Haskell” (the Text), to deal in the Text without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Text, and to permit persons to whom the Text is furnished to do so, subject to the following condition: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Text.