From HaskellWiki
Revision as of 08:31, 7 December 2009 by Ymotongpoo (talk | contribs)

Jump to: navigation, search

Haskellでは とはプログラム内で用いるデータを表現するものです。



data [context =>] type tv1 ... tvi = con1  c1t1 c1c2... c1tn |
                      ... | conm cmt1 ... cmtq


上の宣言の本質は、dataキーワードを使って、付属的なコンテキストを与え、型の名前と多くのtype variableを与えることにあります。 その後、多くのconstructorが続きます。これらはtype variabletype constantのリストになっています。最後に付属的にderivingが続きます。



 data Maybe a = Just a | Nothing

これは、Maybe型はaで表される1つの型変数を持っていて、JustNothingという2つのconstructorを持っているということを意味しています。(Haskellでは型名とコンストラクタ名は大文字で始まらなければいけないことに注意してください) Justコンストラクタは1つのパラメータ"a"をとります。

他の例として、二分木 (binary Tree)を考えてみましょう。このように表されます。

 data Tree a = Branch (Tree a) (Tree a) | Leaf a






 type Name = String



  newtype FirstName = FirstName String


  unFirstName :: FirstName -> String
  unFirstName (FirstName s) = s

これはよくnewtype内のfieldを使うときに行われます。(フィールドを幅広く使う人もいる一方で、多くの人がHaskellのフィールド実装は甘いと考えています。Programming guidelinesFuture of Haskellも参照してください)


Suppose you want to create a program to play bridge. You need something to represent cards. Here is one way to do that.

First, create data types for the suit and card number.

 data Suit = Club | Diamond | Heart | Spade
     deriving (Read, Show, Enum, Eq, Ord)

 data CardValue = Two | Three | Four
     | Five | Six | Seven | Eight | Nine | Ten 
     | Jack | Queen | King | Ace
    deriving (Read,  Show, Enum, Eq, Ord)

Each of these uses a deriving clause to allow us to convert them from / to String and Int, test them for equality and ordering. With types like this, where there are no type variables, equality is based upon which constructor is used and order by the order you wrote them. e.g. Three is less than Queen.

Now we define an actual Card

 data Card = Card {value::CardValue, 
    deriving (Read, Show, Eq)

In this definition, we use fields, which give us ready made functions to access the two parts of a Card. Again, type variables were not used, but the data constructor requires its two parameters to be of specific types, CardValue and Suit.

The deriving clause here only specifies three of our desired Classes, we supply instance declarations for Ord and Enum.

 instance Ord Card where
      compare c1 c2  | (value c1 == (value c2)) = compare (suit c1) (suit c2)
                     | otherwise = compare (value c1) (value c2)

 instance Enum Card where
      toEnum n = Card (toEnum (n `div` 4)) (toEnum (n `mod` 4))
      fromEnum c =  4*(fromEnum (value c)) + (fromEnum (suit c))

Finally, we alias the type Deck to a list of Cards and populate the deck with a list comprehension

 type Deck = [Card]

 deck = [Card val su | val <- [Two .. Ace], su <- [Club .. Spade]]


Further illustrative examples would be most appreciated.


Read the (wanted) articles about data constructors and classes. As well the Haskell 98 report and your chosen implementation (e.g. GHC/Documentation) have the latest words.

Languages: en