[Haskell]:代数的データ型
はじめに
ファンクタを理解するために、代数的データ型や型コンストラクタを知る必要があったため、自分なりに調べてみた。
代数的データ型とは
代数的データ型とは、以下の2つの型を組み合わせたものである。
- 直積型:複数の型を組み合わせて、新しく作成した型
- 直和型:複数の型を組み合わせて、いずれか1つの型を持つ型
直積型
他の言語の構造体
に似たデータ型。
複数の型を記述し、記述した型のそれぞれの値を合わせ持つ新しい型を生成する。
以下の例では、2 つのInt
の値を保持するPoint
型を新しく作成している
例
data Point = Point Int Int
直和型
他の言語の Union 型
に似たデータ型。
|
で区切って記述した複数の選択肢の内、いずれか 1 つを値として取る新しい型を生成する。
以下の例では、曜日の値のどれかを保持するDayOfWeek
型を新しく作成している
例
data DayOfWeek = Mon | Tue | Wed | Thu | Fri | Sat | Sun
直積型 + 直和型
直積型と直和型を組み合わせて、新しいデータ型を定義することもできる。
以下の例では、Circle
型、Rect
型、Triangle
型のいずれかの形を表現するShape
型を新しく作成している
data Shape = Circle Int -- 円(半径)
| Rect Int Int -- 四角形(幅、高さ)
| Triangle Int Int -- 三角形(底辺、高さ)
代数的データ型の定義
代数的データ型の基本的な定義は、以下になる。
data 型コンストラクタ(型名) 型変数 = 値コンストラクタ
-- 例
data Maybe a = Nothing | Just a
-- Mayby:型名
-- a:型変数
-- Nothing:値コンストラクタ
-- Just:値コンストラクタ
型コンストラクタと値コンストラクタ
型コンストラクタ
型コンストラクタは、型を受け取り新しい型を返す。
型コンストラクタは、0 個以上の引数を受け取ることができる。
例
-- 引数なし
data Bool = False | True
-- ^^^^ 型コンストラクタ
data Color = Red | Green | Blue
-- ^^^^^ 型コンストラクタ
-- 引数1つ
data Maybe a = Nothing | Just a
-- ^^^^^ 型コンストラクタ(1引数)
data Box a = Box a
-- ^^^ 型コンストラクタ(1引数)
-- 引数2つ
data Either a b = Left a | Right b
-- ^^^^^^ 型コンストラクタ(2引数)
data Pair a b = Pair a b
-- ^^^^ 型コンストラクタ(2引数)
data First a b = First a
-- ^^^^^ 型コンストラクタ(2引数)
値コンストラクタ(データコンストラクタ)
値コンストラクタは、値を受け取り新しい値を返す。
値コンストラクタは、0 個以上の引数を受け取ることができる。
値をグループ化して、代数的データ型が取り得る値の種類を定義し、実際の値の生成にも使用される。
例
-- 引数:なし
-- Red、Blue、Greenが値コンストラクタに該当
data Color = Red | Blue | Green
-- ^^^^^ 型コンストラクタ
-- ^^^ ^^^^ ^^^^^ 値コンストラクタ(引数なし)
-- 引数:あり
-- 以下が値コンストラクタ
-- Circle Int
-- Rect Int Int
-- Triangle Int Int
data Shape = Circle Int | Rect Int Int | Triangle Int Int
-- ^^^^^ 型コンストラクタ
-- ^^^^^^ 値コンストラクタ(Int -> Shape)
-- ^^^^ 値コンストラクタ(Int -> Int -> Shape)
-- ^^^^^^^^ 値コンストラクタ(Int -> Int -> Shape)
関数として使用して、値を生成する
値コンストラクタは、関数として使用して、値を生成することができる。
data Shape = Circle Int | Rect Int Int| Triangle Int Int deriving Show
radii :: [Int]
radii = [2, 4, 6]
circles :: [Shape]
circles = map Circle radii
main = do
print circles -- [Circle 2,Circle 4,Circle 6]
カインド(種)
カインドとは、大雑把にいうと「型の分類」です。
Haskell のカインドには、以下の 2 つの規則がある。
-
- (A)
*
は、全てのデータ型(値を持つことのできる)のカインドである。
- (A)
-
- (B)
k1 -> k2
は、k1 のカインドを持つ型を受け取り、k2 のカインドの型を生成する。
- (B)
kind は:k
または:kind
を使用することで確認できる。
具体例
(1) 型を受け取らない型(具体型)
Int
やString
など、型引数がない、値を持てる具体型は、カインドが *
になる。
ghci> :k Int
Int :: *
ghci> :k String
String :: *
(2)型引数を受け取る型
Maybe
や[]
など、型引数を受け取る型は、* -> *
のようなカインドになる。
ghci> :k Maybe
Maybe :: * -> * -- 1つの型を受け取る
ghci> :k []
[] :: * -> * -- 1つの型を受け取る
ghci> :k Either
Either :: * -> * -> * -- 2つの型を受け取る
参考
データ型
コンストラクタ
カインド
Discussion