代数的データ型の宣言

data宣言を使って,新しい型を宣言することができる。こんな感じだ。

data Cream = Eric | Jack | Ginger

data に続いて型のなまえ,= の右側には取りうる値を | で区切って列挙する。値は大文字で始まる必要があり,データ構成子(data constructor)という。上の例では,Cream 型は Eric,Jack,Ginger の3つの内のいずれかの値を取る,ということ。

*Main> :t Eric
Eric :: Cream

値は他の型を引数に取ることができる。引数を取る/取らないは混ぜてもいい。

data Cream = Eric Int | Jack Int | Ginger
*Main> :t Eric 10
Eric 10 :: Cream

引数を取らないデータ構成子に引数を与えるとエラーになる。

<interactive>:1:0:
    Couldn't match `Cream' against `t -> t1'
      Expected type: Cream
      Inferred type: t -> t1
    Probable cause: `Ginger' is applied to too many arguments in the call
        (Ginger 10)

逆に引数を取るデータ構成子に引数を与えないと

*Main> :t Jack
Jack :: Int -> Cream

……えーと,これは関数と解釈していいのかな。

*Main> :t Jack (2*2)
Jack (2*2) :: Cream

追記:
上の Jack は関数と考えて良さそうだ。

*Main> :t map Jack
map Jack :: [Int] -> [Cream]

データ構成子が重複すると

エラーになる。たとえば

data Cream = Eric Int | Jack Int | Ginger

data Guiterist = Eric | Bill | Frank | Jeff

これを ghci に読み込むと

*Main> :l datatype.hs
Compiling Main             ( datatype.hs, interpreted )

datatype.hs:3:17:
    Multiple declarations of `Main.Eric'
    Declared at: datatype.hs:1:13
                 datatype.hs:3:17
Failed, modules loaded: none.

と怒られる。モジュールを分けるとか,そういうことで回避できるんだろうけど。