Type classes
하스켈 타입의 예를 들어보면, Bool, Char, 그리고 Integer 등이 있다. 그리고 하스켈은 type classes 도 가지고 있다. 타입 클래스는 해당 타입이 그 타입 클래스의 멤버이기 위해 그 타입이 갖추어야하는 작동을 특정한다.
Num 은 Prelude 에서 정의된 많은 타입 클래스 중의 하나이다. :info Num 을 통해 살펴보면, 타입이 Num 이 되기 위해서는 덧셈, 뺄셈, 곱셈, 그리고 4가지 기능(negate, abs, signNum, fromInteger)을 지원해야 한다. 그리고 Prelude 는 Num 타입 클래스의 4가지 인스턴스를 정의하고 있는데, Int(word-size), Integer (unlimited size), Float 그리고 Double 이 그것이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Prelude> :info Num class Num a where (+) :: a -> a -> a (-) :: a -> a -> a (*) :: a -> a -> a negate :: a -> a abs :: a -> a signum :: a -> a fromInteger :: Integer -> a -- Defined in ‘GHC.Num’ instance Num Word -- Defined in ‘GHC.Num’ instance Num Integer -- Defined in ‘GHC.Num’ instance Num Int -- Defined in ‘GHC.Num’ instance Num Float -- Defined in ‘GHC.Float’ instance Num Double -- Defined in ‘GHC.Float’ Prelude> | cs |
아래에서 negate 의 타입을 살펴보자.
1 2 3 | Prelude> :type negate negate :: Num a => a -> a | cs |
negate 의 타입은 type variable 인 a 를 통해 특정되어 있다. a -> a 라는 부분이 말하는 것은 negate 는 인수로 전달받은 것과 같은 타입을 가진 값을 반환한다는 것이다. 즉, Int 를 주면 나도 Int 를 돌려주겠다는 식이다.
그리고 Num a => 라는 부분은 class constraint 이다. 타입 a 는 타입 클래스 Num 의 인스턴스여야함을 특정하는 것이다.
negate는 타입이 Num의 인스턴스인 어떤 값이라도 받아들인다. 그리고 같은 타입의 값을 반환한다.
integer literals 은 어떤 타입을 갖는지 살펴보자.
1 2 3 4 5 | Prelude> :type 3 3 :: Num a => a Prelude> :type (-27) (-27) :: Num a => a | cs |
Num class constraint 를 갖는 Literals 의 경우, Num a => a 를 받아들이는 모든 함수에 의해 사용가능하다. 그럼 negate 3.4 은 유효하게 작동하는가?
1 2 3 4 5 6 7 8 9 | Prelude> :type negate negate :: Num a => a -> a Prelude> :type 3.4 3.4 :: Fractional a => a Prelude> negate 3.4 -3.4 it :: Fractional a => a | cs |
하스켈의 타입 클래스는 계층구조를 지닌다. Prelude 의 경우 다음과 같은 계층구조를 가진다.
Num Int, Integer, Float, Double |
→ |
Fractional Float, Double |
위의 이미지에 나와있는 관계 중 하나인 Num → Fractional 을 보자. 여기서 Num 에서 Fractional 으로 가는 화살표가 의미하는 것은 Fractional 이 Num 으로 사용가능하다는 이야기이다. 따라서 negate :: Num a => a -> a 와 5.0 :: Fractional a => a 이라면, negate 5.0 역시 유효하다는 이야기이다.
negate :: Num a => a -> a 는 아래와 같이 여러 함수를 나타낸다.
negate :: Integer -> Integer
negate :: Int -> Int
negate :: Float -> Float
negate :: Double -> Double
negate 는 다형 함수로, 다양한 형태의 값을 다룰 수 있다. 만약 함수의 타입이 type variables 을 가지고 있다면, 그 함수는 다형 함수라고 할 수 있다.
'프로그래밍 Programming' 카테고리의 다른 글
Functional Programming with Haskell - Loading functions from a file (0) | 2018.03.30 |
---|---|
Functional Programming with Haskell - Simple functions (0) | 2018.03.30 |
하스켈 모듈 언로딩 How to go back to prelude> in ghci (0) | 2018.03.27 |
Functional Programming with Haskell - Function types (0) | 2018.03.24 |
Functional Programming with Haskell - Calling functions (0) | 2018.03.24 |