幽霊型
PhantomType
以下の様な型のxのこと
code:hs
data PhantomType x a = PhantomType a
左辺では2つの型変数を取るが、右辺では一つの型しか使っていない
使われていない型のことを幽霊型と呼ぶ
この例ではx
何が嬉しいのか
こういう型を定義したときに
code:hs
data PhantomType x a = PhantomType a
こういうふうに型を別物として扱うことができる
code:hs
data PostId
data UserId
type UID = PhantomType UserId Int
type PID = PhantomType PostId Int
UIDもPIDも型のbodyは同じくPhantomType Intである
であるにも関わらずUIDとPIDは全く別物として扱うことができる
仮に幽霊型を使っていなければ以下のようになる
code:hs
data Id a = Id a
type PostId = Int
type UserId = Int
type UID = Id UserId
type PID = Id PostId
PostIdもUserIdも実質Intなので、
UIDとPIDは両方とも実質Id Intとなり、区別がつかない
どこで使えるのか
同じprimitiveな型だが区別したいときに使える
暗号文(Int)と平文(Int)
PostId(Int)とUserId(Int)
日付(String)
日付にも時間を含むものと、含まないものある
両方ともにStringだとうまく解析が出来なくてバグる
newtypeがあるのになぜ幽霊型が必要になる?
こうすると型のbodyが異なるものになっちゃうから?
code:hs
newtype PostId = PostId Int
newtype UserId = UserId Int
つまりbodyが異なるものでも良くて、primitiveな型を区別したいケースなら幽霊型は必要にならない
「幽霊型」の指すものが曖昧
定義: data PhantomType x a = PhantomTypeC a
使用: PhantomType X A
とするときに、
Xのことを幽霊型と呼ぶ派
PhantomTypeのことを幽霊型と呼ぶ派
その他
などあって人によってバラバラ
言語別
TypeScript
Scala
Haskell
わかりやすいが、コメントでも指摘されている通り例が少し適切でない
OCaml
Elm
Rust
Swift
参考
https://www.youtube.com/watch?v=cyOvlaweUtw&feature=youtu.be