Hatena::Grouphaskell

lnzntのHaskell日記 このページをアンテナに追加 RSSフィード

2014年11月24日(月)

| 16:48 |  型 - lnzntのHaskell日記 を含むブックマーク はてなブックマーク -  型 - lnzntのHaskell日記  型 - lnzntのHaskell日記 のブックマークコメント

型と型クラス。自分には難解です。

とりあえず、参考書籍見ながら勉強したことをメモしておく。

----

data 宣言

新しい型を定義するには「data 宣言」を使う。

data 宣言で定義できる型は代数的データ型(algebraic*1 type)と呼ばれる。

例えば、以下。HTML の A 要素を表す型。String 型の「フィールド」を2つもつ、と宣言してみる。

data A = A String String

data の次の A が「型名」であり「型コンストラクタ」である。(後述の型変数を使った宣言でないので両者は一致している)

等号(=) の次の A が「データコンストラクタ(値コンストラクタ)」。

型コンストラクタデータコンストラクタは異なる名前空間にあるので同じ名前でもよい。

使うのは、以下のような感じ。

data A = A String String

innerHtml :: A -> String
innerHtml (A uri label) = "<a href=\"" ++ uri ++ "\">" ++ label ++ "</a>"

main = do
    print $ innerHtml (A "http://localhost/" "myComputer")
                       -- <a href="http://localhost/">myComputer</a> と表示される

あるいは、こんな感じ。

data A = A String String

anchorUri :: A -> String
anchorUri (A uri label) = uri

aElement = A "http://localhost/" "myComputer"

main = do
    print $ anchorUri aElement        -- "http://localhost/" と表示される
フィールドラベル

フィールドフィールドラベルを付けて宣言することもできる。

data A = A { aUri :: String, aLabel :: String }

使うのは、こんな感じ。

data A = A { aUri :: String,  aLabel :: String }

anchorUri :: A -> String
anchorUri (A { aUri = u } ) = u

aElement = A "http://localhost/" "myComputer"

main = do
    print $ anchorUri aElement        -- "http://localhost/" と表示される
セレクタ

セレクタ」とはフィールドラベルと同名のフィールドラベルの値を取得できる関数。これは自動的に定義される。

data A = A { aUri :: String,  aLabel :: String }

aElement = A "http://localhost/" "myComputer"

main = do
    print $ (aUri aElement)           -- "http://localhost/" と表示される
フィールドの更新

以下のように、フィールドの値を別の値にして値全体を作りなおすことができる。

data A = A { aUri :: String,  aLabel :: String }

aElement = A "http://localhost/" "myComputer"

main = do
    print $ (aUri aElement)
                    -- "http://localhost/" と表示される
    print $ (aUri aElement { aUri = "http://127.0.0.1" })
                    -- "http://127.0.0.1/" と表示される   
「|」を使った宣言

こんな感じ。

data Element = A   { aUri :: String,  aLabel :: String }
             | IMG { aSrc :: String }

isA :: Element -> Bool
isA (A _ _) = True
isA _       = False

isIMG :: Element -> Bool
isIMG (IMG _) = True
isIMG _       = False

aElement = A "http://localhost/" "myComputer"

main = do
    print $ isA aElement      -- True  と表示される
    print $ isIMG aElement    -- False と表示される
型変数を使った宣言
data MyStack a = MyStack [a]

boolStack    = MyStack [True, False]
intStack     = MyStack [1, 2, 10, 100]
stringStack  = MyStack ["foo","bar"]

型名は「MyStack a」。型コンストラクタは「MyStack」。

データコンストラクタも「MyStack」(こっちは等号の(=) の次のMyStack)。

type 宣言

既存の型の別名を宣言する。

type FilePath = String
type MyList [a] = [a]

newtype 宣言

既存の型を元に新しい型を宣言する。

newtype MyStack a = MyStack [a]

data 宣言との違いがよくわからないのですが、以下の記事に「値コンストラクタが正格であること」が違いだと書かれていました。難しい。。。

*1:「あるじぇぶりっく」または「あるじぇぶらいく」と読む