代数的データ型

data宣言

新しい型を定義する

data 型コンストラクタ 型変数1 型変数2 ...
    = データコンストラクタA 型A1 型A2 ...
    | データコンストラクタB 型B1 型B2 ...
    | データコンストラクタC 型C1 型C2 ...
                :
  • 型コンストラクタとデータコンストラクタの名前空間は別(同じ名前が使える)
  • 再帰的に書ける(データコンストラクタの引数の型に今定義している型コンストラクタを書ける)
    • 例) data Stack a = Empty | Push a (Stack a)
  • パターンマッチによるフィールドへのアクセス
    • 例)compileAnchor (A url label) = ...

フィールドラベルの設定

data Anchor = A { aURL   :: String,  -- フィールドラベル"aURL"
                  aLabel :: String } -- フィールドラベル"aLabel"
        deriving Show

compileAnchor (A {aUrl = u, aLabel = l})   -- u,lをそれぞれのフィールドに束縛
      = "<a href=\"" ++ u ++ "\">" ++ l ++ "</a>"

main = let href = A "http://example.com/" "Foo"
       in do print (aLabel href)
               -- セレクタ: フィールドラベルと同名の関数(getter)
             print (href { aLabel = "Bar" })
               -- hrefのaLabelを変更した新たなAnchorの値を作り出す
             print compileAnchor href
               -- hrefのaLabelは"Foo"のまま

type宣言

  • 型に別名をつける
  • 新しいデータコンストラクタは導入されない
type 型コンストラクタ 型変数1 型変数2 ... = 型

newtype宣言

  • 元になる型のフィールドを一つだけ含む代数的データ型を宣言する
  • 今いち使いどころがわからん。data使えばいいのでは?
newtype 型コンストラクタ 型変数1 型変数2 ... = データコンストラクタ 型