私は Learn You a Haskell を読んだだけで得られたので、意味のあるDataKinds拡張機能の説明を見つけようとしています。私が学んだ小さなことで私にとって意味のある標準的なソースはありますか?
編集:たとえば documentation は
-XDataKindsを使用すると、GHCは適切なすべてのデータ型を種類に自動的に昇格させ、その(値)コンストラクターを型コンストラクターに昇格させます。次のタイプ
そして例を与える
data Nat = Ze | Su Nat
次の種類と型コンストラクタを生成します。
Nat :: BOX
Ze :: Nat
Su :: Nat -> Nat
私はポイントを得ていません。 BOX
の意味はわかりませんが、ステートメントZe :: Nat
およびSu :: Nat -> Nat
は、ZeとSuがghciで予想されるとおりに通常のデータコンストラクターである場合に、すでに通常何であるかを述べているようです。
Prelude> :t Su
Su :: Nat -> Nat
それでは基本から始めましょう
種類は、たとえば*の種類です
Int :: *
Bool :: *
Maybe :: * -> *
->
は、種類レベルでも「関数」を意味するようにオーバーロードされています。そう *
は、通常のHaskellタイプの一種です。
GHCiに、:k
。
独自の種類を作成する方法がないため、これはあまり有用ではありません! DataKinds
を使用すると、
data Nat = S Nat | Z
GHCはこれを促進して、対応する種類Nat
を作成し、
Prelude> :k S
S :: Nat -> Nat
Prelude> :k Z
Z :: Nat
したがって、DataKind
sはkindシステムを拡張可能にします。
GADTを使用してプロトタイプの種類の例をやってみましょう
data Vec :: Nat -> * where
Nil :: Vec Z
Cons :: Int -> Vec n -> Vec (S n)
これで、Vec
型が長さでインデックス付けされていることがわかります。
これが基本的な10kフィートの概要です。
*これは実際に続きます、Values : Types : Kinds : Sorts ...
一部の言語(Coq、Agda ..)は、この無限の宇宙のスタックをサポートしていますが、Haskellはすべてを1つの種類にまとめています。
私の見解は次のとおりです。
次のタイプの長さインデックス付きベクターを考えます。
data Vec n a where
Vnil :: Vec Zero a
Vcons :: a -> Vec n a -> Vec (Succ n) a
data Zero
data Succ a
ここに種類Vec :: * -> * -> *
があります。ゼロの長さのInt Vectorを次のように表現できるため、
Vect Zero Int
また、次のような意味のない型を宣言することもできます。
Vect Bool Int
これは、型レベルで型指定のない関数型プログラミングができることを意味します。したがって、データの種類を導入することでこのようなあいまいさを取り除き、そのような種類を持つことができます。
Vec :: Nat -> * -> *
Vec
はNat
という名前のDataKindを取得し、次のように宣言できます。
datakind Nat = Zero | Succ Nat
新しいデータの種類を導入することにより、Vec
にはより制約のある種類の署名が追加されたため、誰も無意味な型を宣言できません。