트랙
/
Gleam
Gleam
/
학습 과정
/
팬텀 타입
팬텀

팬텀 타입 에서 Gleam

1개의 연습 문제

팬텀 타입 소개

팬텀 타입은 사용자 정의 타입의 타입 매개변수 중에서, 그 타입의 값 생성자 어디에서도 사용되지 않는 것을 말해요.

조금 추상적이니 예시를 하나 볼까요?

pub type Length(unit) {
  Length(amount: Float)
}

이 예시에서 unit 타입 매개변수는 Length 값 생성자에서 사용되지 않아요. 그래서 unit은 팬텀 타입이에요.

이렇게 사용되지 않는 타입 매개변수는 쓸모없어 보일 수 있지만, Length 값을 어떻게 쓸 수 있는지에 제약을 더하는 데 활용할 수 있어요.

예를 들어 길이를 두 배로 만드는 double 함수를 생각해봐요. 이 함수는 어떤 단위의 길이와도 동작하기 때문에, 타입 매개변수가 제네릭 타입 변수가 돼요.

// This function accepts all Length values
pub fn double(length: Length(unit)) -> Length(unit) {
  Length(length.amount *. 2.0)
}

길이가 인치일 때만 동작하는 add_inch 함수도 만들 수 있어요.

// A unit type for inches. It is never constructed so we don't
// define any constructors for it.
pub type Inches

pub fn add_inch(length: Length(Inches)) -> Length(Inches) {
  Length(length.amount +. 1.0)
}

add_inch 함수는 다른 단위 매개변수를 가진 길이는 받지 않아요. 팬텀 타입을 이용해 올바른 단위만 쓰이도록 한 거예요.

같은 타입 변수를 둘 다에 사용해서, 두 길이 값이 같은 단위임을 보장하는 함수를 작성할 수도 있어요.

pub fn add(a: Length(unit), b: Length(unit)) -> Length(unit) {
  Length(a.amount +. b.amount)
}
let two_meters: Length(Meters) = Length(2.0)
let two_inches: Length(Inches) = Length(2.0)

add(two_meters, two_meters)
// -> Length(4.0): Length(Meters)

add(two_meters, two_inches)
// Type error! The unit type parameters do not match.

팬텀 타입은 불투명 타입과 잘 어울려요. 다른 모듈에서 Length 값을 만들 수 없다면, 잘못된 단위 타입으로 값이 만들어지지 않도록 보장할 수 있고, 위에서 정의한 함수들만 그 값에 쓸 수 있게 할 수 있어요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요

팬텀 타입 배우기