前回の続き
Haskell を使ってみる 4 (タプル) - kntmr-blog
型宣言
式の型は :t
コマンドで調べることができる。::
は xxx の型を持つことを意味する。
Prelude> :t 'a' -- Char 型 'a' :: Char Prelude> :t "Hello" -- Char 型のリスト "Hello" :: [Char] Prelude> :t ('a',True) -- (Char 型, Bool 型) を持つ (タプルは個々の要素が型を持つ) ('a',True) :: (Char, Bool)
関数に明示的な型宣言を与えることができる。
removeLowercase :: [Char] -> [Char] -- 引数に1つの文字列を取って別の文字列を返すことを意味する
型変数
型変数を使うことで、型安全を保ったまま関数を複数の型に対して動作させることができる。
Prelude> :t head head :: [a] -> a -- a が型変数で、任意の型を引数に取ることを表す
型変数を使った関数は多相的関数と呼ばれる。head
関数の場合、任意の型のリストを引数に取り、その型の要素を1つ返すことを表す。
型クラス
型クラスは何らかの振る舞いを定義するインタフェース。ある型クラスのインスタンスである型は、型クラスが持つ振る舞いを実装する。型クラスは関数の集まりで、ある型クラスに属する関数をその型クラスのメソッドと呼ぶ。
Prelude> :t (==) (==) :: Eq a => a -> a -> Bool
=>
は型クラス制約と呼ばれる。等値性関数の場合、同じ型の引数を2つ取って Bool 型を返すことを表す。また、引数の型は Eq クラスのインスタンスであることを意味する。
等値性演算子 (==
) は、実際には関数である。関数名が特殊文字から構成される場合、デフォルトで中置関数となる。その型を調べる場合や他の関数に渡す場合、前置関数として呼び出す場合は、丸括弧で囲う。
Eq 型クラス
等値性をテストできる型に使われる。Eq のインスタンスは ==
と /=
を実装する。Haskell のすべての標準型は Eq のインスタンスである。
関数の型変数に Eq クラスの制約が付いている場合、その関数の定義のどこかで ==
か /=
が使われていることを意味する。
Ord 型クラス
何らかの順序を付けられる型のための型クラス。比較演算子 (>
) の場合、引数を2つ取り、それらが関係を満たすかどうかを表す Bool を返す。compare
関数の場合、Ord のインスタンスの型の引数を2つ取って Ordering を返す。Ordering は GT
, LT
, EQ
のいずれかの値を取る型。
Prelude> :t (>) (>) :: Ord a => a -> a -> Bool Prelude> :t compare compare :: Ord a => a -> a -> Ordering Prelude> "abc" < "xyz" True Prelude> "abc" `compare` "xyz" LT
Show 型クラス
ある値の型が Show 型のインスタンスであれば、文字列として表現することができる。show
関数は、ある型のインスタンスを引数に1つ取って文字列を返す。
Prelude> :t show show :: Show a => a -> String Prelude> show 1 "1" Prelude> show 3.14 "3.14" Prelude> show True "True"
Read 型クラス
文字列を受け取り、任意の型のインスタンスの値を返すための型クラス。read
関数は、文字列を受け取り、Read のインスタンスの型の値を返す。
Prelude> :t read read :: Read a => String -> a Prelude> read "1" + 2 3 Prelude> read "[1,2,3,4]" ++ [5] [1,2,3,4,5]
read
関数が返す値の型は Read のインスタンスであるが、具体的にどの型を返すかは返す値の使い方次第で判定する。式が取るべき型を明示する場合には型注釈 (::
) を使う。
Prelude> read "1" -- これはエラー (返り値の型を推論できない) *** Exception: Prelude.read: no parse Prelude> read "1" :: Int -- 型注釈で型を指定する 1
Enum 型クラス
要素の値を列挙するための型クラス。Enum 型クラスのインスタンスの値はレンジの中で使うことができる。Enum のインスタンスの型には、後者関数 succ
や前者関数 pred
が定義されている。
Prelude> succ '1' '2' Prelude> pred True False
Bounded 型クラス
上限と下限を持つインスタンスを表すための型クラス。minBound
関数と maxBound
関数で調べることができる。
Prelude> :t minBound minBound :: Bounded a => a -- 多相定数 (定数だが任意の型として振る舞うことができる) Prelude> minBound :: Int -9223372036854775808 Prelude> maxBound :: Char '\1114111'
タプルを構成する要素がすべて Bounded のインスタンスであれば、そのタプル自身も Bounded になる。
Prelude> maxBound :: (Bool, Int, Char) (True,9223372036854775807,'\1114111')
Num 型クラス
数を表すための型クラス。あらゆる数は多相定数として表されており、Num 型クラスの任意のインスタンスとして振る舞うことができる。
Prelude> 1 :: Int 1 Prelude> 1 :: Integer 1 Prelude> 1 :: Float 1.0 Prelude> 1 :: Double 1.0
*
演算子は、2つの数を引数に取って1つの数を返す。3つの数はすべて同じ型であることを意味する。
Prelude> :t (*) (*) :: Num a => a -> a -> a
同時に複数の型のインスタンスとして振る舞うことはできない。
Prelude> (5 :: Int) * (10 :: Integer) -- これは型エラーとなる <interactive>:109:15: error: • Couldn't match expected type ‘Int’ with actual type ‘Integer’ • In the second argument of ‘(*)’, namely ‘(10 :: Integer)’ In the expression: (5 :: Int) * (10 :: Integer) In an equation for ‘it’: it = (5 :: Int) * (10 :: Integer)
Floating 型クラス
浮動小数点数を表すための型クラス。この型クラスには Float と Double が含まれる。
Integral 型クラス
整数を表すための型クラス。この型クラスには Int と Integer が含まれる。Num は実数を含むすべての数を表す。fromIntegral
関数は何らかの整数を引数に取ってより一般的な数 (Num) を返す。整数と浮動小数点数を一緒に扱うような場合に使う。
Prelude> :t fromIntegral fromIntegral :: (Num b, Integral a) => a -> b Prelude> fromIntegral (1 :: Int) + 2.1 3.1 Prelude> (1 :: Int) + 2.0 -- これはエラー (Int と浮動小数点数を足し合わせようとしているため) <interactive>:123:14: error: • No instance for (Fractional Int) arising from the literal ‘2.0’ • In the second argument of ‘(+)’, namely ‘2.0’ In the expression: (1 :: Int) + 2.0 In an equation for ‘it’: it = (1 :: Int) + 2.0
今回は型について。