はじめに
-
すごいHaskellたのしく学ぼうを読んだのでちょっとずつまとめていきたい。まとめていきたい。
-
シリーズ
Haskellの型
型を確認してみる
- ghciに
:t
と打ち込むと型を表示できる
*Main Lib> :t 'a' -- シングルクォーテーション、1文字
'a' :: Char
*Main Lib> :t 'ab' -- シングルクォーテーション、複数文字
<interactive>:1:1: error:
? Syntax error on 'ab'
Perhaps you intended to use TemplateHaskell or TemplateHaskellQuotes
? In the Template Haskell quotation 'ab'
*Main Lib> :t "aiueo" -- ダブルクォーテーション、複数文字
"aiueo" :: [Char]
*Main Lib> :t True -- 真偽値
True :: Bool
- 値に対する型の表示は「値
::
型」というフォーマットで出力される。
関数の型
- Haskellは関数の型を明示的に宣言することができる。
isZero :: Int -> Bool -- 引数 -> 戻り値
isZero x = x == 0 -- Int型のxを受け取ってそれが0より大きいかどうかをBool型で返す。
*Main> isZero 9
False
-- 引数が複数ある場合は
-- 「引数 -> 引数 -> ...-> 戻り値」の順に型を定義する。
addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z
型の種類
型 | 説明 |
---|---|
Int | 整数 |
Integer | 巨大な整数 |
Float | 浮動小数点数 |
Double | 倍精度浮動小数点数(Floatの2倍のbit数で少数を表すので精度高まる) |
Bool | TrueとFalseの2つを表す |
Char | Unicode文字 |
タプル | ()の中の要素数と要素の型に依存して型が決まる。空のタプルも() の型を持つ |
- Haskellにおける文字列は文字のリストとして考えることができる
*Main Lib> ['a','i','u','e','o'] == "aiueo" -- 左右は同じもの
True
型変数
- takeの型を確認するとリストの中身にaと入っている。
*Main> :t take
take :: Int -> [a] -> [a]
*Main> take 3 "aiueo" -- 文字列は文字のリスト
"aiu"
- takeは指定された数の分だけ、リストの先頭を取り出す関数。
*Main> take 2 [1,2,3]
[1,2]
- リストの中身はどんな型でも気にしない。そのため、
a
と表記することで、「どんな型でもいいですよ」を表す。 -
a
のようなものを型変数
と呼ぶ -
型変数
を用いた関数は多相的関数
と呼ぶ
型クラス
型クラスとは
- ある
型
に特定の関数を適用したときの振る舞い
を定義するもの - 型と型クラスは多体多の関係
- 文章ではなんだかよくわからないので具体例を確認する。
例(等値性)
-
(==)
関数の型を確認してみる。(* (==)という書き方についてはこちら)
ghci> :t (==)
(==) ::(Eq a) => a -> a -> Bool
- いままで見たことない
=>
という書き方とその左側にある(Eq a)
なるもの。ここが型クラス。 -
=>
より右は同じ型の値を2つ突っ込んだら真偽値が入るという関数の型(私達は既に知っているはず。)
(Eq a) => a -> a -> Bool
-
(Eq a)
は「Eq
において性質が保証された型a
」というふうに読める。 -
A => B
は「AならばがB成立する。」と考えて大丈夫そうなので -
(Eq a) => 左辺
で「Eqという性質を満たす型aならば左辺が成立」と読める。 -
a
が型変数ということはIntやリストなど、様々な型についてEqによる等値性の定義がされていると考えられる。
具体的に値を入れて関数を実行してみると
*Main> (==) [1,2,3] [1,2,3]
True
*Main> (==) [1,2,3] [1,2,2] -- 要素数が同じだけではFalse
False
- 要素数が一緒なだけでなく、要素のパターンまで同じでないと
(==)
関数の結果がTrueにならないのは、Eqがリストの等値性をそういう定義にしているからなのである。 - 型クラスはこういう風に「ある
型
に特定の関数を適用したときの振る舞い
を定義」する
他の型クラス
- Show
文字列として表現できるもの
*Main> :t show --show関数の定義をみると
show :: Show a => a -> String -- Show型クラスを条件にした定義が書いてある。
-- 関数名と型クラス名が同じで分かり辛いが大文字から始まるShowは「文字列として表現できる」ということを表す型クラス。
-- showは「与えられた型を文字列にする」関数
*Main> show 1
"1"
*Main> show 3.0
"3.0"
*Main> show 'a'
"'a'"
*Main> show "aaa"
"\"aaa\""
*Main> show True
"True"
*Main> show False
"False"
*Main> show [1,2,3,4]
"[1,2,3,4]"
- Num
数のように振る舞えるもの
*Main> :t (+) -- 足し算の型確認
(+) :: Num a => a -> a -> a -- 数のように振る舞えるならなんでも足し算していい
*Main> (+) 20 30 --整数でも
50
*Main> (+) 20.0 30.0 -- 浮動小数点数でもね
50.0
他にも
- Ord(順番がある)
- Enum(列挙可能)
- Bounded(上限と下限をもつ)
- Floating(浮動少数点数のみ)
- Integral(実数のみ)
とかの型クラスで型の性質を定義できる。(基本的な型クラスの定義はHaskellがやっといてくれる)