もしRubyistがHaskellを学んだら(20) Data.Mapによる連想配列
タグ: learning_haskell / 初版公開: 2014-01-18

Rubyには連想配列を表すHashクラスが用意されており、文法上もHashを定義するリテラルが存在するなど手厚いサポートがされている。ではHaskellはどうか。Haskellでは連想配列はData.Mapモジュールで提供されている。今日はRubyのHashと、HaskellのData.Mapの使い方を以下のRubyのコードを元に比較してゆきたい。

phoneBook = {"alice" => "1234-5678", "bob" => "2345-6789", "carol" => "3456-7890"}
p phoneBook["alice"] # => "1234-5678"
phoneBook.store("carol", "3456-7890")
p phoneBook["carol"] # => "3456-7890"
phoneBook.delete("bob")
p phoneBook["bob"] # => nil

このRubyのコードは、電話帳を操作するものだ。電話帳はHashのインスタンスで表現し、名前をキーに、電話番号を値とする連想配列とする。まず電話帳を初期化し、それに対して電話帳の項目の追加、削除と名前から電話番号の検索を行う。これをHaskellで実装してみることにする。

import qualified Data.Map as Map
phoneBook :: Map.Map String String
phoneBook = Map.fromList [("alice", "1234-5678"), ("bob", "2345-6789")]
main = do 
	print $ Map.lookup "alice" phoneBook -- => Just "1234-5678"
	let phoneBook2 = Map.insert "carol" "3456-7890" phoneBook 
	print $ Map.lookup "carol" phoneBook2 -- => Just "3456-7890"
	let phoneBook3 = Map.delete "bob" phoneBook2
	print $ Map.lookup "bob" phoneBook3 -- => Nothing

HaskellではまずData.Mapモジュールを使用するためにこれを修飾つきでimpomtする。これはPreludeの関数とData.Mapの関数が一部重複するため、明示的にMapを指定しなければData.Mapの関数を呼び出せない形でインポートするためである。RubyのHashとHaskellのData.Mapの基本的なメソッドの対応は以下のとおり。

Ruby Data.Map 意味
{}リテラル Data.Map.fromList 連想配列を初期化する
[] Data.Map.lookup キーに対応する値を取得する
store Data.Map.insert キーに対応する値を設定する
delete Data.Map.delete キーとその値を削除する

HaskellではfromLinstを使ってタプル(ペア)のリストから連想配列を初期化できる。 Haskellの関数はいずれも連想配列自体は変更せずに、新しい連想配列を返すようになっている。 そのためinsertdelete毎に新しい連想配列を変数に束縛している。 これはちょっと不恰好に見えるのだが、直接連想配列を操作する方法は見当たらなかった。

注目すべきはlookup関数の型である。これをGHCiで調べてみると以下のようにMaybeがついた特別な型が返ることがわかる。これはその型の値か、Nothingが返ることを意味している。実際、電話帳からbobの項目を削除したあとでbobを検索するとNothingが返ってくることがわかる。

*Main> :t Map.lookup
Map.lookup :: Ord k => k -> Map.Map k a -> Maybe a

なおHaskellのプログラムで頻出している$$に続く関数の評価を優先して行うためのシンタックスシュガーである。printの例ではprint $ 1 + 1print (1 + 1)が等価である。$以降がすべて括弧で囲われているものと思えば良い。

電話帳を題材にしたData.Mapの使い方については、”すごいHaskellたのしく学ぼう!”の6章を参考にした。本書ではまず自力でタプルとリストを使った連想リストを実装したあとに、Data.Mapを導入する流れとなっており、良い勉強になる。

すごいHaskellたのしく学ぼう!
Miran Lipovača
オーム社
売り上げランキング: 126,678