PR

文字列リテラルからByteStringやTextを直接作成する

 第2回で紹介したbytestringパッケージのByteString型では,文字列リテラルを使って表現されたString型からByteString型に変換するためにpack関数を利用していました。

Prelude Data.ByteString.Char8> :t pack
pack :: String -> ByteString
Prelude Data.ByteString.Char8> pack "ring"
"ring"

 同様に第45回のコラムで紹介したtextパッケージでも,文字列リテラルを使って表現されたString型からText型への変換にはpack関数を利用する必要がありました。

Prelude Data.Text> :t pack
pack :: String -> Text
Prelude Data.Text> pack "ring"
"ring"

 文字列リテラルから目的の型のデータを作成するために,このようにいちいちpack関数を利用するのは面倒です。そこでGHCでは,文字列リテラルから目的の型を直接作成できるようにする拡張機能を提供しています。Data.Stringモジュールで提供されているIsStringクラスと,文字列リテラルの型をString型から「IsStringクラスのインスタンスである型」に拡張するための機能であるOverloadedStringsです。

 IsStringクラスのfromStringメソッドは,文字通りStringからIsStringクラスのインスタンスである型への変換を定義する関数です。

class IsString a where
    fromString :: String -> a

instance IsString [Char] where
    fromString xs = xs

 ライブラリの作者や型を利用するプログラマがIsStringクラスのインスタンスとfromStringメソッドを定義し,-X*オプションまたはLANGUAGE指示文でOverloadedStringsを指定することで,数値リテラルなどの他のリテラルと同様に,文字列リテラルを様々な型に多重定義して利用できるようになります(参考リンク1参考リンク2)。

Prelude> :t "ring"
"ring" :: [Char]
Prelude> :set -XOverloadedStrings
Prelude> :t "ring"
"ring" :: Data.String.IsString a => a
Prelude Data.ByteString> "ring"::String
"ring"

 ByteStringやTextでは,文字列リテラルを利用できるように,IsStringクラスのインスタンスがすでに用意されています(参考リンク1参考リンク2)。したがって,-X*オプションまたはLANGUAGE指示文でOverloadedStringsを指定するだけで,pack関数を使わなくても文字列リテラルからByteStringやTextを直接作成できます。

Prelude Data.ByteString> "ring"::ByteString
"ring"
Prelude Data.ByteString> :m Data.Text
Prelude Data.Text> "ring"::Text
"ring"


著者紹介 shelarcy

 今回は,並列プログラムの効率化の原則を説明しました。2011年7月時点での並列Haskellやデータ並列Haskellの内部実装を題材にしましたが,特定の並列処理機能やライブラリに依存することのない,他の並列処理機能にも適用できる基本的な考え方を説明したつもりです。

 もちろん,実際に並行/並列プログラムを効率化するには,基本的な考え方だけでなく,処理系の実装に依存した細かい知識も必要です。例えば,並列Haskellでは実際にどのようにして処理が並列化されているかは「Runtime Support for Multicore Haskell」という論文で説明されています。また,現在のGHCのSTMの実装で性能を出すにはどのようにプログラムを書けばいいのかを知りたければ「Comparing the performance of concurrent linked-list implementations in Haskell」という論文が参考になります。

 ですが,こうした処理系の実装に依存する知識は,実装が変化すれば役に立たなくなる可能性があります。まずは,今回説明した基本的な考え方を押さえておいてください。

 なお,今回は例として並列処理版のクイックソート関数を取り上げましたが,同じく第11回で取り上げた,並列処理版の素数列生成プログラムも,高速なプログラムにはなっていません。高速な素数列の生成に興味がある方は,Haskell Wikiの"Prime numbers"のページ,およびそのページのリンク先にあるライブラリや文献を参照してください。