generated at
DataKinds
以下のような昇格ができるGHC拡張
GHC v7.4.1で入った

data Nat = Zero | Succ Nat のような型を定義したとき
普通は値コンストラクタ Zero , Succ kindは定義されていない
DataKindsを用いると
型→kindと昇格されるので、型がkindとして表示される
値→型と昇格されるので、値のkindを調べることができる
hs
{-# LANGUAGE DataKinds #-} data Nat = Zero | Succ Nat
こう変わる
beforeafter
> :k Nat**
> :k SuccerrorNat -> Natここが変わる
> :k ZeroerrorNatここが変わる
> :t Naterrorerror
> :t SuccNat -> NatNat -> Nat
> :t ZeroNatNat
DataKindsを使うと以下の3つが新たに暗黙に定義されている
kindとしての Nat
型コンストラクタとしての Succ
型コンストラクタとしての Zero
こうなると、元の世界の Nat , Succ , Zero と名前が被ってしまう
しかし文脈(書く場所)で区別できるので、推論されるため特に気にする必要はない
しかし人間にとってわかりやすくする為に、新しく定義された方は、頭に ' を付けて明示もできる
e.g. 'Succ , 'Zero
kindとしての Nat は、 'Nat と書いても同じ意味だが、人間が書くことはないのであまりその表記はされないと思うmrsekut
上の表のghciの出力結果はわざわざ ' を付けないためやや分かりづらい
上の表をこれを区別して書くと
こう変わる
after
> :k Nat*
> :k 'Succ'Nat -> 'Nat
> :k 'Zero'Nat
> :t Naterror
> :t SuccNat -> Nat
> :t ZeroNat
昇格されたとて、 'Succ 'Zero は具体型ではないことに注意
具体型はkindが * になるので


' がないと区別できないパターン
data Hoge a = Hoge a のような型を定義した場合に、
値コンストラクタの方(右辺)の Hoge から生成される型コンストラクタのkindは、 ' がないと区別できない
ghci
:k Hoge > Hoge :: * -> * :k 'Hoge > 'Hoge :: a -> Hoge a



生成されたものはこういう対応になっている
対応
元の世界DataKindsの世界
kind-
型コンストラクタkind型コンストラクタを種へ昇格している
値コンストラクタ型コンストラクタ値コンストラクタを型コンストラクタへ昇格している
-値コンストラクタ
data A a = B a というような型を定義した場合
data A a = B a
元の世界DataKindsの世界
* -> *-
A a''A a
B a'B a
-
元の世界の A a a は任意の型を表すが、DataKindsの世界の A a a は任意のkindを表す
身近な具体例として
Bool = True | False
元の世界DataKindsの世界
*-
Bool'Bool
True'True
-
だから :k 'Hoge と、 :t Hoge は見た目が同じ感じの出力に鳴る
見た目が同じだけで概念は異なる
「元の世界に存在しないもの」が、「DataKinds世界の値」になっているので、
DataKinds世界の 'B a 型や 'True 型になるような値は存在しない




KindSignaturesと組み合わせることで自作型をkind制約として書くことができる
例えば要素数を型引数に含む Vector n b 型の定義 ref
n には自然数型、 b には要素の型を取る、ということを明示する
いめーじ.hs
{-# LANGUAGE DataKinds #-} {-# LANGUAGE KindSignatures #-} data Nat = Zero | Succ Nat data Vector (n :: Nat) (b :: *) = ..



:k * :k *->* の結果が、 * なのと同じように、
:k 'Nat の結果も * になっても良い気もするけどならないんだねmrsekut
つまり、kindの上の概念としての 'Nat は新たに定義はされていない


応用例
tagとして使う ref



参考
シンプルでわかりやすい
丁寧だが、型と値に同じ文字列を使っていて微妙にわかりづらさ増してる気がする
じっくり読むならよい