前回の続き
Haskell を使ってみる 4 (タプル) - kntmr-blog
型宣言
式の型は :t
コマンドで調べることができる。::
は xxx の型を持つことを意味する。
Prelude> :t 'a'
'a' :: Char
Prelude> :t "Hello"
"Hello" :: [Char]
Prelude> :t ('a',True)
('a',True) :: (Char, Bool)
関数に明示的な型宣言を与えることができる。
removeLowercase :: [Char] -> [Char]
型変数
型変数を使うことで、型安全を保ったまま関数を複数の型に対して動作させることができる。
Prelude> :t head
head :: [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 のインスタンスの型には、後者関数 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
<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
今回は型について。