Haskell の文字列は, 歴史的な事情で, 若干複雑になっています。
1文字を表すのは Char型です。値の意味は Unicode code point です。なので、厳密には「文字」ではない。
リテラルは「'」で文字を囲みます。
Prelude> :type 'あ' 'あ' :: Char
文字リテラルでは, \x に続けて16進数で10ffffまでのcode point を指定できます。これを超える値の場合は out of range エラー。
Char型は次の型クラスのインスタンスです。
BoundedEnumEqDataOrdReadShowIxStorableIsCharPrintfArg
TODO: このほか data family URec のインスタンス?
組込みの文字列型は String です。String は [Char], つまりCharのリスト型の別名になっています。
String は素朴な1文字単位のリストなので, 想像どおり, パフォーマンスに難があります。過去との互換性のために残っています。
新しいプログラムでは, バイト列がほしいときは ByteString, 文字列がほしいときは Text データ型を使ってください。
type String = [Char] -- Defined in `GHC.Base'
リテラルは「"」で囲みます。String型は単なるリストなので、その値の操作については, リストに適用できる関数がそのまま使えます。
次のプログラムは, ファイルの先頭を表示します。
それぞれの関数:
readFile :: FilePath -> IO String
lines :: String -> [String]
ただし, 元の文字列の末尾の改行文字は単に除去されるため, 元の文字列に厳密に復元できるようにはなっていません。
Prelude> lines "fuga\r\n" ["fuga\r"]
take :: Int -> [a] -> [a]
unlines :: [String] -> String
doブロックについては, またページを替えて説明しますが, とりあえずここでは,
<-キーワードで, 右辺のアクション (IO a型の値) を左辺のa型の定数に割り当てることができます。
ByteStringデータ型bytestring パッケージの Data.ByteString モジュール, ByteString データ型は, 単なるバイトの配列です。型名に〜Stringが含まれていますが, 文字列は関係ありません。
ByteString は, 次の型クラスのインスタンスです。
EqDataOrdReadShowIsStringMonoidNFData
とはいえ, 単に右から左へデータを移すようなときは, ByteString が使えます。
OverloadedStrings で、文字列リテラルが String型以外になりえます。IsString型クラスのインスタンス (で型が合うもの) になる。
実行例
何か入力> ああ愛 str = ああ愛 9 bytes
単にそのまま表示するだけなら, ただのバイト列なので, 化けません。この例だと, 文字数は UTF-8によるバイト数の9になっています。
本物の文字列は, Text 型です。
入出力は ByteString を使い, 文字列に変換して使います。
"str2.txt"ファイル (UTF-8で保存。)
あああAbc23はひふ
実行結果:
$ runhaskell str2.hs 12
改行文字込みで, 正しく12文字とカウントできている。
Text型については、別ページに続きます; テキスト型の周辺