理想未来ってなんやねん

娘可愛い。お父さん頑張る。

Haskell 8日目

Haskell 8日目。

今日は『第6章 基本的な値』の後半です。

文字と文字列

文字型

Haskellの文字型はChar型で、文字コードUnicodeが使われます。
GHCでは文字自体はUnicodeで表現されているものの、入出力での文字コードの変換などは実装されていない。

Haskellでは文字と数字は別物で、数値として扱いたい時にはChar.odd関数やChar.chr関数を使って明示的に整数と相互変換する必要がある。

文字リテラルは『' '』を使って表現し、文字リテラルではエスケープシーケンスが使えます。

主要なエスケープシーケンス

記述例 意味
\t タブ
\n 改行
\r 復帰
\v 垂直タブ
\f 改ページ
\a ベル
\b バックスペース
\NNN 10進数の数値NNNに対応する文字
\oNN 8進数の数値NNNに対応する文字
\xNN 16進数の数値NNNに対応する文字
\^X コントロールX
\' シングルクォート
\" ダブルクォート
\\ バックスラッシュ(環境により¥記号)
文字列型

Haskellの文字列は文字のリストで、その方は[Char]型です。
[Char]の別名としてStringも使用できます。

文字列リテラル中では、文字リテラルと同じエスケープシーケンスが使えます。

文字種のテスト関数
適用例 意味
isAlpha c 文字cがUnicodeのアルファベットならばTrue
isLower c 文字cがUnicodeのアルファベット小文字ならばTrue
isUpper c 文字cがUnicodeのアルファベット大文字ならばTrue
isAlphaNum c 文字cがUnicodeのアルファベットまたは数字ならばTrue
isDigit c 文字cが数字(0〜9)ならばTrue
isHexDigit c 文字cが数値の16審表記で使われる文字('0'〜'9'、'a'〜'f'、'A'〜'F')ならTrue
isOctDigit c 文字cが数値の8審表記で使われる文字('0'〜'7')ならTrue
isSpace c 文字cが空白文字(''、'\t'、'\n'、'\r'、'\v'、'\f'およびLatin1の空白類)ならTrue
isAscii c 文字cがASCIIに含まれる文字ならTrue
isLatin1 c 文字cがLatin1の文字('\0'〜'\255')ならばTrue
isPrint c 文字cがUnicodeの表示可能文字ならばTrue
isControl c 文字cがLatin 1の表示不可能文字ならばTrue
大文字・小文字の変換関数
適用例 意味
toLower c 文字cを小文字に変換
toUpper c 文字cを大文字に変換
文字と整数との変換
適用例 意味
ord c 文字cの文字コードを返す
chr n 文字コードnに対応する文字を返す

タプル

タプル(tuple)とはいくつかの値の組です。
複数の値をまとめるという点でリストに似ていますが、要素の個数と順序まで含めて型が決まるという点が違います。
(Int、String)型は(String、Int)型とも(Int、String、Int)型とも違います。

タプルのリテラルの例と型

(3, "string")  :: (Int, String)
("lucky", 7)  :: (Int, String)
(1, "string", [5, 3, 3])  :: (Int, String, [Int])
('a', "string", (1, 3))  :: (Int, String, (Int, Int))

タプルは基本的に2要素以上でなければならず、1要素のタプルというものはありませんが、特別に0要素のタプルはあり、そのタプルはユニットと呼ばれます。

ユニットとは

0要素のタプルで、ソースコード上では( )と記述されます。
ユニットの型はリテラルと同じく『( )』です。
ユニットは『値がない』ことを示すときにつかわれ、例えばアクション『putStr "str"』の型は『IO ()』で、『意味のある結果を残さないアクション』という意味になります。

タプルを扱う関数
適用例 意味
fst pair 2要素タプルの第1要素を返す。
snd pair 2要素タプルの第2要素を返す。
zip xs ys リストxsとysの各要素を横に繋いだタプルのリストを返す。xsとysの長さが違う時は短い方に揃えられます。
unzip xs タプルのリストをリストのタプルに変換します。

リスト

リストは同じ型の値を並べたものです。Haskellのリストは一方向性で前から後ろにたどる事はできてもその逆はできない。

要素の型がaであるリストの型は『[a]』と書きます。

[]
[1, 2, 3]
['a', 'b', 'c']
['a', 'bbb', 'cc']
[['a', 'a'], [['b', 'b', 'b'], ['c', 'c']]

文字列は文字のリストとしても書けますが、簡潔に書く為に文字列専用のリテラルが用意されています。

"string"

リストには、『:』演算子を使った表現も用意されています。本来はこちらの『:』演算子を使った表現が正式で、[]を使った形式が略記です。

リストの数列表記

一定範囲の整数や文字などを表記する特殊な記法があります。

[1..7]     -- [1, 2, 3, 4, 5, 6, 7]と同じ
['a'..'e'] -- ['a', 'b', 'c', 'd', 'e']と同じ
[1, 3..11] -- [1, 3, 5, 7, 9, 11]と同じ
[1..]      -- [1, 2, 3, 4, 5, 6, ....]と同じ
[1, 3..]   -- [1, 3, 5, 7, 9, 11, ....]と同じ

..の表記は無限リストの表記です。

リストに関する関数

リストに関する重要な関数で説明がまだ出てきていないものは次のとおり。

適用例 意味
null xs xsが空リストならTrueを返す
xs ++ ys 2つのリストxsとysを連結したリストを返します。
リスト内包表記

Haskellにはmap関数やfilter関数を組み合わせた関数を数学的に表現するリスト内包表記という構文があります。

[abs x| x <- xs]

この内包表記は『リストxsの各要素xについて(abs x)を集める』と読みます。
map関数を使って書くなら以下のようになります。

map abs xs

リスト内包表記を使ったコード例としてはクイックソートを実現したqsort関数が良く挙げられます。

qsort []     = []
qsort (p:xs) = qsort lt ++ [p] ++ qsort qteq
                where
                  lt   = [x | x <- xs, x < p]
                  qteq = [x | x <- xs, x >= p]

この内包表記はfilter関数の別表現で、[y | y <- xs, y < x]は『リストxsの各要素yについて、y < xである要素を集める』と読みます。


今日のところはここまで
明日は『第7章 基本的な構文』に進みます。