第10章 型とクラスの定義 #1

10.1 typeによる型宣言

typeキーワードは型のエイリアスに名前をつける方法。再帰定義はできない。

type Assoc k v = [(k,v)]

find     :: Eq k => k -> Assoc k v -> v
find k t =  head [v | (k',v) <- t, k == k']

newtypeキーワードは教科書に出て来てないなあ。

10.2 dataによる型宣言

dataはデータコンストラクタ(構築子)を並べる型宣言。 下の例だと、LeftRightUpDownが引数なしのデータコンストラクタ。 要するに、型Moveは列挙型ということ。

-- nullary data constructor
type Pos = (Int,Int)
data Move = Left_ | Right_ | Up_ | Down_

move              :: Move -> Pos -> Pos
move Left_ (x,y)  =  (x-1,  y)
move Right_ (x,y) =  (x+1,  y)
move Up_ (x,y)    =  (  x,y-1)
move Down_ (x,y)  =  (  x,y+1)

moves          :: [Move] -> Pos -> Pos
moves [] p     =  p
moves (m:ms) p =  moves ms (move m p)

flip        :: Move -> Move
flip Left_  =  Right_
flip Right_ =  Left_
flip Up_    =  Down_
flip Down_  =  Up_

下の例は、Circleが1引数のデータコンストラクタ、Rectが2引数のデータコンストラクタ。

-- unary/binary data constructor
data Shape = Circle Float | Rect Float Float

square   :: Float -> Shape
square n =  Rect n n

area            :: Shape -> Float
area (Circle r) =  pi * r ^ 2
area (Rect x y) =  x * y

多相型(型引数付き)も定義可能。ここでMaybe aが例に登場。

-- polymorphic data constructor with a type parameter
-- (data Maybe a = Nothing | Just a)
safediv     :: Int -> Int -> Maybe Int
safediv _ 0 =  Nothing
safediv m n = Just (m `div` n)

safehead    :: [a] -> Maybe a
safehead [] =  Nothing
safehead xs =  Just (head xs)