さて、Haskellには "class", "data", "instance", "type" という予約語がありますが、一般的な(オブジェクト指向言語における)意味と全然違うので注意が必要です。
普通に考えると、
- class: クラス定義?
- data: インスタンス生成?
- instance: dataと同じ・・・?
- type: ???
- class: インターフェイス定義用。Javaのinterfaceに近い。
- data: 構造体定義用。Cのstructに近い。
- instance: 構造体に属性を定義する。強いて言えばJavaのimplementsに近い。
- type: 型の同名 (synonim) を作る。Cのtypedef。
例としてBookという型を考えます。
data Book = Book {Javaで書くとこう(動くことを確認していません。最近Java触って無いので間違ってるかも)。
title :: String,
authors :: [String],
isbn :: Int
}
b = Book "Enjoy Haskell" ["Alice", "Bob"], 12345678
class Book {(ISBNがintで表現できるのかという問題は無視します。)
public String title;
public ArrayListauthors;
public int isbn;
}
Book b = new Book;
b.title = "Enjoy Haskell";
b.authors = new ArrayList; // あと省略
b.isbn = 12345678;
これでBookクラスを定義できましたが、これだけだといろいろ不便です。例えば(非常に恣意的な例ですが・・・)大小判定ができません。ghciで試してみると・・・
*Main> let b1 = Book "Enjoy Haskell" ["Alice", "Bob"] 1234と、エラーになります。
*Main> let b2 = Book "Scala Sucks" ["Charlie", "Daniela"] 5678
*Main> b1 < b2
:1:0:
No instance for (Ord Book)
arising from a use of `<' at:1:0-6
Possible fix: add an instance declaration for (Ord Book)
In the expression: b1 < b2
In the definition of `it': it = b1 < b2
ご丁寧に"Possible fix: add an instance declaration for (Ord Book)"と、修正方法を教えてくれました。instance declarationを追加してみます。
instance Eq Book where(今必要なのは、Ord Bookの宣言ですが、OrdはEqのサブクラス(のようなもの)なので、Eq Bookも定義しなくてはいけません。)
(==) a b = (isbn a) == (isbn b)
instance Ord Book where
compare a b = compare (isbn a) (isbn b)
これで、大小比較できるようになります。
Javaで同じ事をやるには、Comparableというインターフェイス(で定義されているcomparaメソッド)を実装します。
class Book implements Comparable {
public int compare(Object o) { return isbn - (Book o).isbn; }
public String title;
// 省略
}
というように、Javaでimplementsを使うべきところ、つまりクラスにある性質を追加したいときに、Haskellではinstanceを使います。そして、EqやOrdを"type class"と呼びます。で、type classを定義するのに使う予約語が"class"です。例えばEqとOrdの定義はこうです。
class Eq a wheretype classが持つべきメソッドの型を定義しています。Javaだとこうですね。
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<) :: a -> a -> Bool
(>=) :: a -> a -> Bool
(>) :: a -> a -> Bool
(<=) :: a -> a -> Bool
max :: a -> a -> a
min :: a -> a -> a
interface Comparable extends Eq {
// "extends Eq"はHaskellとの比較のためにつけただけで、実際には不要。
int compare(Object o);
}
このように、"class", "data", "instance"をJavaと対応付けることで、理解しやすくなると思います。
最後に残った"type"ですが、これはCのtypedefと同じです。
type ErrorNo = IntCではこうですね。
typedef int ErrorNo;別名をつけただけなので、型チェックでは同じ型だとみなされるのもCと同じです。下のコードはtype checkをパスします。
f :: ErrorNo -> String
f e = "Hello World!"
g :: Int -> String
g i = f i
ということで、Haskellにでてくる型関連の予約語を整理してみました。
0 件のコメント:
コメントを投稿