シリーズ :: [Qiita記事]
Haskell個人メモ :: 1.基本
Haskell個人メモ :: 2.型 ←いまここ
Haskell個人メモ :: 3.関数の構文
Haskell個人メモ :: 4.再帰
明示的な型指定
5 :: Int -- 5
5 :: Float -- 5.0
値 :: 型
と書くことで明示的に型を指定できる。
値
はxxx型
によって表現される、と読むと分かりやすいかも。
:t 'A' -- 'A' :: Char
:t "Hello" -- "Hello" :: [Char]
REPLだと:t 値
で実際の型が何かを調べられる。
(純粋関数型言語なので)関数も値の一種なので、:t 関数
で型を調べられる。
Haskellの一般的な型
型 | 説明 |
---|---|
Int | 整数 |
Integer | 限界がない整数(固定のビット長を持たない) |
Float | 単精度浮動小数点 |
Double | 倍精度浮動小数点 |
Bool | True / False |
Char | 文字(Unicode) |
タプル | 最大数は62 |
型変数
:t take -- take :: Int -> [a] -> [a]
上記におけるa
が「型変数」で、他の言語で言うところのジェネリクス。
つまり、中身の型(ここではリストの要素の型)を限定しない時に使う。
ちなみに型変数を用いた関数を「多相的関数」を呼ぶ。
(呼び方の問題なのであまり重要ではないけれど)
:t fst -- fst :: (a, b) -> a
同じ型変数が指定されている場合(上記ではa
)、はそれらは同じ型でなければならない。
逆に異なっている型変数(上記ではa
とb
)が、異なる型である必要はない。
型クラス
基本
:t (==) -- (==) :: Eq a => a -> a -> Bool
Javaでいうところの「インターフェース」、Objective-C / Swift でいうところの「プロトコル」。
(既存の型を含めて、拡張できるという意味ではSwiftのプロトコル/エクステンションが非常に近い)
上記のEq
が「型クラス」の例で、等値性をテストするためのインターフェースを定義している。
(具体的には==
と/=
の2つ)
型クラス制約
Eq a =>
は「型クラス制約」と呼び、a
がEq
型クラスの関数を実装している必要があること示す。
つまり、a
は==
と/=
で比較可能でなければならない。
他言語で言えば、引数として「インターフェース」や「プロトコル」が要求されているイメージ。
インスタンス
ある「型」が、ある「型クラス」に適合している場合、(その型はある型クラスの)「インスタンス」である、と表現する。
例えば、自作の型Foo
をEq
型クラスに適合する場合、「Foo
型をEq
型クラスのインスタンスにする」と表現する。
型
+型クラス
=インスタンス化
、みたいなイメージを持つと分かりやすいかも。
用語のまとめ
| 型 | 説明 | コード例 |
| :------------- | :------------- | :------------- | :------------- |
| 型クラス | 振る舞いを定義するインターフェース | Eq
|
| 型クラス制約 | その型が準拠していなければならない型クラスを指定 | Eq a =>
|
| インスタンス | 型クラスに準拠している型 | - |
標準の型クラス(の例)
| 型クラス (*1) | 振る舞い | インターフェース |
| :------------- | :------------- | :------------- | :------------- |
| Eq | 等値性のテスト | ==
/=
|
| Ord(Eq) | 順序付け | >
<
>=
<=
compare
|
| Show | 文字列として表現可能 | show
|
| Read | 文字列から値を復元可能 | read
|
| Enum | 値を列挙できる | succ
pred
|
| Bounded | 上限と下限を持つ | maxBound
minBound
|
| Num | 数 | +
-
*
他 |
| Fractional(Num) | 分数 | /
他 |
| Floating(Fractional) | 浮動小数点 | sin
cos
tan
他 |
| Integral(Num) | 整数(全体) | div
mod
他 |
*1 ()内は前提となる型クラス。例えば、Ord
のインスタンスになるためには、Eq
インスタンスでなければならない。