第4回 再帰とデータ型の話をしよう

山下 伸夫
株式会社タイムインターメディア

2009/2/16

文字と文字列

 文字データの型はCharで、文字リテラルはシングルクオート「'」で文字を囲んで表す。

 文字列データの型はStringで、文字列リテラルはダブルクオート「"」で文字列を囲む。

Prelude> 'a'
'a'
Prelude> "a"
"a"
Prelude> "This is a character string."
"This is a character string."
Prelude> ""
""
Prelude> ''

<interactive>:1:1:
    lexical error in string/character literal at character '\''
Prelude Data.Char>

 文字'a'と文字列"a"は別ものなので注意してほしい。'a'はアルファベットの最初の文字の小文字である。"a"は'a'を1字だけ含む文字列だ。空の文字列""は存在するが、空の文字というのは存在しない。

 文字関連のユーティリティ関数はData.Charモジュールで定義されているので、文字や文字列を扱うときは、このモジュールをインポートして使う。ghci上でモジュールを新たにインポートするときは、:moduleコマンドを使う。

Prelude> :module + Data.Char
Prelude Data.Char> _

 ghciのデフォルトの設定では、新たにモジュールを追加インポートするとプロンプトにも追加したモジュール名が現れるようになる。

Prelude Data.Char> toUpper 'a'
'A'
Prelude Data.Char> toLower 'A'
'a'

 日本語の扱いは現在のところ少し工夫が必要となる。これについては次回以降で説明する。

リスト

 値の集合や並びを表現するには、リストというデータ構造を使う。リストはHaskellでは最も重要なデータ構造の1つである。どのように表現されるかghciを使って試してみよう。

注:
ghciの起動オプション-v0は、ghciが起動時にバージョン情報やモジュールのロード情報などの表示を抑制するものである

$ ghci -v0
Prelude> _

 リストは複数の値(を表わす式)を含んでいるデータ構造である。これを直接表現するには、要素をコンマ「,」で区切り、全体を角括弧「[ ]」で囲む。要素を持たない空のリストというものも [ ]で表現できる。

Prelude> [1,2,3]
[1,2,3]
Prelude> []
[]
Prelude> ["foo","bar","baz","quux","fnord","xyzzy"]
["foo","bar","baz","quux","fnord","xyzzy"]

 リストの型は、要素の型を角括弧で囲んで表す。

ints :: [Int]
ints = [1,2,3,4,5]

strs :: [String]
strs = ["hoge","huga","hage","hige"]

 リストは以下のように構成できる値である。

  1. 空リスト[ ]はリスト
  2. 要素になる値(を表す式)をリストの先頭に加えたものはリスト

 1と2の手順で構成できるもののみがリストである。

 このように、最も基本的な構成(この場合、空リスト)から始めて、繰り返し積み上げて、データ構造を構成していく方法を帰納的構成という。また、このような方法で定義されているデータ型を「帰納的に構成されたデータ型」という。

 リストはHaskellでは組み込みであるが、実質以下のように定義されている(実際は、組み込みで定義されているので以下のようなコードはHaskellでは不正である)。

data [a] = []
         | a : [a]

 少し分かりにくいので説明しよう。型 [a]と表現するのと、型 [ ] aと表現するのは同じことを表現している。型を表す場合、 [ ]は引数(これも型を表現するもの)を1つ取る型構成子である。

 [a]は要素の型がaであるようなリスト型、すなわち「aのリスト」型である。data宣言の右辺は、先ほどのリストの構成法の1と2に対応している。右辺の [ ]は空リストを表すデータ構成子である。2行目は「:」がデータ構成子である。

 Haskellでは「:」で始まり、記号だけで構成されるデータ構成子が使える。これは2項演算子と同じ使い方をする。すなわち、2つの引数の間に置く。

Prelude> 1:[]
[1]
Prelude> 2:(3:(4:[]))
[2,3,4]
Prelude> 1:[2,3,4]
[1,2,3,4]

 「:」はデータ構成子であるが、左側の値を右側のリストに追加する2項演算子と見なせる。この場合、「:」は右結合性を持つので、2:(3:(4:[]))は2:3:4:[]と書いてもよい。

Prelude> 2:3:4:[]
[2,3,4]

文字列は文字のリスト

 文字列の型はStringであるが、これはPrelude内で、

type String = [Char]

と宣言されているので、実は文字のリストなのである。文字列リテラルのダブルクオートで囲う書き方は、リストの要素が文字である [Char]型の値の場合にのみ使える記法ともいえる。

Prelude> :type ['s','t','r','i','n','g']
['s','t','r','i','n','g'] :: [Char]
Prelude> ['s','t','r','i','n','g']
"string"
Prelude> :type "string"
"string" :: [Char]
prelude> 'a':' ':"string"
"a string"

 文字列はリストなので、文字列処理のほとんどはリスト処理である。リスト処理はHaskellの基本であり、そのための関数は多くPreludeに含まれている。それゆえ、Preludeにあるリスト関連の関数を習熟するとHaskellプログラミングがぐっと楽しくなる。

 次回はプログラムを通じてリスト処理について解説する。

3/3
 

Index
再帰とデータ型の話をしよう
  Page1
階乗を計算する関数
階段の昇り方
  Page2
計算の効率
データ型の話をしよう
論理値型
数値型
Page3
文字と文字列
リスト
文字列は文字のリスト
のんびりHaskell

 Coding Edgeお勧め記事
いまさらアルゴリズムを学ぶ意味
コーディングに役立つ! アルゴリズムの基本(1)
 コンピュータに「3の倍数と3の付く数字」を判断させるにはどうしたらいいか。発想力を鍛えよう
Zope 3の魅力に迫る
Zope 3とは何ぞや?(1)
 Pythonで書かれたWebアプリケーションフレームワーク「Zope 3」。ほかのソフトウェアとは一体何が違っているのか?
貧弱環境プログラミングのススメ
柴田 淳のコーディング天国
 高性能なIT機器に囲まれた環境でコンピュータの動作原理に触れることは可能だろうか。貧弱なPC上にビットマップの直線をどうやって引く?
Haskellプログラミングの楽しみ方
のんびりHaskell(1)
 関数型言語に分類されるHaskell。C言語などの手続き型言語とまったく異なるプログラミングの世界に踏み出してみよう
ちょっと変わったLisp入門
Gaucheでメタプログラミング(1)
 Lispの一種であるScheme。いくつかある処理系の中でも気軽にスクリプトを書けるGaucheでLispの世界を体験してみよう
  Coding Edgeフォーラムフィード  2.01.00.91


Coding Edge フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

>

Coding Edge 記事ランキング

本日 月間