📓

[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 つの規則がある。

    1. (A)*は、全てのデータ型(値を持つことのできる)のカインドである。
    1. (B)k1 -> k2 は、k1 のカインドを持つ型を受け取り、k2 のカインドの型を生成する。

kind は:kまたは:kindを使用することで確認できる。

具体例

(1) 型を受け取らない型(具体型)

IntStringなど、型引数がない、値を持てる具体型は、カインドが * になる。

ghci> :k Int
Int :: *

ghci> :k String
String :: *

(2)型引数を受け取る型

Maybe[]など、型引数を受け取る型は、* -> *のようなカインドになる。

ghci> :k Maybe
Maybe :: * -> * -- 1つの型を受け取る

ghci> :k []
[] :: * -> * -- 1つの型を受け取る

ghci> :k Either
Either :: * -> * -> *  -- 2つの型を受け取る

参考

データ型

http://walk.northcol.org/haskell/adts/
https://qiita.com/7shi/items/1ce76bde464b4a55c143

コンストラクタ

https://wiki.haskell.org/Constructor#Type_constructor
https://zenn.dev/mod_poppo/books/haskell-type-level-programming/viewer/types-and-kinds
https://takafumi-s.hatenablog.com/entry/2015/09/25/123335

カインド

https://ja.wikipedia.org/wiki/カインド_(型理論)
https://qiita.com/tobita_yoshiki/items/a2ffd2cefa53376338c6
https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/poly_kinds.html#overview-of-type-in-type
https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/poly_kinds.html#the-kind-type

Discussion