generated at
幽霊型
PhantomType
以下の様な型の x のこと
hs
data PhantomType x a = PhantomType a
左辺では2つの型変数を取るが、右辺では一つの型しか使っていない
使われていない型のことを幽霊型と呼ぶ
この例では x
「Phaontom Type」はDomain Specific Embedded Compilersという論文が出典らしい?

何が嬉しいのか
こういう型を定義したときに
hs
data PhantomType x a = PhantomType a
こういうふうに型を別物として扱うことができる
hs
data PostId data UserId type UID = PhantomType UserId Int type PID = PhantomType PostId Int
UID PID も型のbodyは同じく PhantomType Int である
であるにも関わらず UID PID は全く別物として扱うことができる
仮に幽霊型を使っていなければ以下のようになる
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が異なるものになっちゃうから?
hs
newtype PostId = PostId Int newtype UserId = UserId Int
つまりbodyが異なるものでも良くて、primitiveな型を区別したいケースなら幽霊型は必要にならない


「幽霊型」の指すものが曖昧
定義: data PhantomType x a = PhantomTypeC a
使用: PhantomType X A
とするときに、 
X のことを幽霊型と呼ぶ派
PhantomType のことを幽霊型と呼ぶ派
その他
などあって人によってバラバラ



言語別
TypeScript
構造的部分型なのでbranded typesを使うと良い
Scala
Haskell
わかりやすいが、コメントでも指摘されている通り例が少し適切でない
OCaml
Elm
Rust
Swift


参考