본문 바로가기

프로그래밍 기술 노트/Functional Study

[Expression Problem] Type classes

 

 

type class 는 Haskell (및 Scala + implicit .. , Rust) 에서 주로 사용하는 기능으로

adhoc (임시적) 다형성을 제공하는 기술이다. (Haskell 을 해본적이 없어서 설명이나 예시가 정확하지는 않음..)

type class 를 상속받으면 해당 기능을 구현해야 하고, 해당 type class 에 대한 다형성을 가짐

엥 이거 완전 interface 아니냐?

Interface 를 상속 받으면 해당 기능을 구현해야 하고, 해당 interface 에 대한 다형성을 가짐

그럼 인터페이스와 차이가 뭘까?

interface 는 해당 interface 를 상속 받기위해서는 class가 선언됨과 동시에 어떤 다형성을 가질지 Interface 를 명시해야한다

interface Character {
    fun hit()
    fun skill()
}

interface Monster {
    fun bark()
}

class Tanker : Character, Monster {
    val hp: Int = 100
    override fun hit() { println("Tanker Hit") }
    override fun skill() { println("Tanker Skill") }
    override fun bark() { println("Tanker Skill") }
}

이 코드는 가능해도

interface Character {
    fun hit()
    fun skill()
}

interface Monster {
    fun bark()
}

class Tanker : Character{
    val hp: Int = 100
    override fun hit() { println("Tanker Hit") }
    override fun skill() { println("Tanker Skill") }
}

// 오랜시간이 지난후..


class Tanker : Monster {
    override fun bark() { println("Monster bark") }
}

이건 안된다는 말이다.

 

그러나 Type class 는 다르다, Type class는 인스턴스화 할때, 그 대상이 Implicit(암시적)으로 타입클래스의 기능을 가지게 된다.

-- 기존의 FP 식 정의 -> 기본적으로 Close 한 타입이므로 해당 타입에 대해여 확장은 X 
-- data Character = Healer Int |  Knight Int


-- 확장을 위해서는 type class 사용 -> 기본적으로 각 데이터는 무관함
data Healer =  Healer Int
data Knight  = Knight Int

-- 각 type 을 Type Class 로 정의?함
class Character c 
instance Character Healer
instance Character Knight

 


즉 Implicit (암시적으로) 적용되는 Adhoc(임시적) 인터페이스 같은 녀석이다.

-- Monster는 bark 함수를 가지는 Type class, Character Type class 로 부터 drived 됨
class (Character c) => Monster c where
  bark :: c -> String

-- Healer 는 이제 Monster type class 의 함수가 정의될 수 있음
instance Monster Healer where
  bark (Healer x) = blahblah

Healer 는 이제(Adhoc) skill/hit/bark 를 모두 가진다. (FP 처럼 함수를 확장)

 

-- 새 Type 이 정의되는것도 가능 (like Interface)
data Tanker =  blah blah

instance Character Tanker

Tanker 는 Character 를 구현한 data 이다. (인터페이스처럼 서브타입 확장)

type class 를 사용하면 두개 모두 가능하다. 와~~

 

하지만 type class의 문제점은, type class는 type class 이지 type 이 아니라는 점이다 (??)

 let x = 20
 let who = if x > 4 then (Healer 100) else (Knight 100) #-> Error!!

who의 Type 은 Healer 가 될수도, Knight 가 될수도 있다. (x 값에 따라)

haskell 은 강력한 정적 타입언어이므로, who 의 타입이 (컴파일 타임에) 명확하게 추론되어야 하는데, 우리는 Healer 와 Knight 를 adhoc(임시적) 으로 묶어놓은것이므로, 위와 같은 코드가 불가능하다.

진짜 안되네

 

그래서... type 을 만들고 type 컨스트럭터를 이용해서 두개를 아주 복잡하게 적절하게 사용해서 문제를 해결할수있지만, 일단 어렵고, 포스팅의 범위를 넘어가는것 같아서 생략.. [자세한 설명] 참조

728x90