Haskellの型システムについて

Haskellでは2種類のpolymorphismがサポートされている。それはParametric PolymorphismとAd-hoc Polymorphismである。

  • Parametric Polymorphism

型に関わらず同じ操作を行う場合に発生するpolymorphism。例えばソートアルゴリズム等は要素の比較や同一性判定に使用する部分を除いては、要素の型に依存しないのでparametric polymorphismを持つ。例えばC++のテンプレート。

  • Ad-hoc Polymorphism

型の種類に依存して、行われる操作が異なる場合に発生するpolymorphism。例えばC言語における+演算子はint, floatの両方の型に適応できるが、内部で使用されているアルゴリズムは全く異なる。

以上2つのpolymorphismの概念を理解した上で、Haskellのclass, instanceキーワードをみていく。

  • Parametric Polymorphism

例えばlength関数。

length :: [a] ~> Integer
length [] = 0
length (x:xs) = 1 + length xs

この関数は、リストの中身の型がどのような型で有っても適応可能である。

length [1, 2, 3] => 3
length ['a', 'b', 'c'] => 3
length [[1], [2], [3]] => 3
  • Ad-hoc Polymorphism

JavaC++ではclass定義にメンバ変数等のデータ構造の定義と関数の定義の両方を記述するが、Haskellではそれが分離されており、class定義にはそのclassに属する関数(method)だけを定義する。Javaのインターフェースに相当すると言って良いかも。

class Eq a where
  (==) :: a -> a -> Bool

instanceを使用して、Eqで定義されている== methodを再定義する。

instance Eq Integer where
  x == y = x `integerEq` y

これでInteger型に== methodを追加する事が出来る。

      • -

Haskellには他にも型に関連するものとしてdata, typeというキーワードが有る。

  • data

dataは以下のようにして用い、1つまたはそれ以上のdata constructorを定義する。

data Bool = False
           | True

data Point a = Pt a a

Boolの様に複数のdata constructorが有る型を(disjoint) unionやsum typesと呼ぶ。逆に一つのdata constructorしか持たないPointのような型をtuple typeと呼ぶ。

Pointの所を見ると、ここにもPolymorphismが登場している。例えばPt data constructorを使用して以下の様にデータを構築できる。

Pt 2.0 3.0
Pt 'a' 'a'
Pt True False

Pt :: a -> a -> Point aである為に、内容の型には無関係となる。

  • type

typeは既にある型に対して別名を付けるためのキーワードだ。

type String = [Char]
type Person = (Name, Address)
type Name = String
data Address = None | Addr String

Polymorphicな型の別名を付ける事もできる。

type AssocList a b = [(a, b)]