확장 GeneralisedNewtypeDeriving (GeneralizedNewtypeDeriving) (작성 중)

Posted on September 21, 2023

6.6.5. Generalised derived instance for newtypes
재미난게, 영어 스펠링이 나라에 따라 sz가 쓰이고 있어, Generalised(영국), Generalized 둘 다 준비 해놨습니다.

newtype Dollars = Dollars Int

이 확장이 없이 Dollars를 더하기 하려면, 명시적으로 DollarsNum클래스의 인스턴스로 정의해야 합니다.

instance Num Dollars where
  Dollars a + Dollars b = Dollars (a + b)
  ^^^^^^^     ^^^^^^^     ^^^^^^^

위 인스턴스 정의가 하는 일은 Dollars 생성자를 적용하는 일만 하고 있습니다. 생성자는 런타임에선 사라지기 때문에, 이 인스턴스 선언은 Int 딕셔너리1와 완전히 동일한 정의입니다.

※ 이 아이디어를 일반화한 게 확장 DerivingVia 입니다.

GeneralisedNewtypeDeriving 확장을 켜면, 다음처럼만 쓰면 GHC가 인스턴스를 유도해 줍니다.

newtype Dollars = Dollars { getDollars :: Int } deriving (Eq, Show, Num)

구현은 IntNum 딕셔너리를 씁니다. 다시 말해, GHC가 다음과 비슷한 걸 생성합니다.

instance Num Int => Num Dollars

※ 위 표현이 낯섭니다. Num Int란 제약이 있는데 => 오른 쪽에 Int가 없습니다. Dollars가 안에 Int를 가지고 있긴 한데, 이런 식으로 써도 되는지 아직 “문법” 자체를 잘 모르겠습니다.

GHC는 Num Int 인스턴스가 유효 스코프에 있는 걸 알기 때문에, 다음 처럼만 생성합니다.

instance Num Dollars

…작성 중


  1. 타입이 갖고 있는 인스턴스 목록을 타입 클래스 딕셔너리, 혹은 그냥 딕셔너리라고 하는 것 같습니다.↩︎

Github 계정이 없는 분은 메일로 보내주세요. lionhairdino at gmail.com