2012年 12月 17日
ユニコード表作成の続きだ。といっても、残り作業はほんのちょっと。
先頭の数字を16進数表示に直せばよいだけだ。
行の先頭に最初の文字のコードを10進数で追加していたのはこれだ。
addhead xa@(x:_) = show (ord x) ++ " " ++ xa
show (ord x) で、文字x の文字コードが出ていた。
16進数は、show の代わりに showHex でできるらしい。
しかし、Numericのインポートが必要だ。
*Main Data.List> import Numeric
*Main Data.List Numeric> showHex 1000
>interactive>:34:1:
No instance for (Show ShowS)
arising from a use of `print'
Possible fix: add an instance declaration for (Show ShowS)
In a stmt of an interactive GHCi command: print it
*Main Data.List Numeric>
importしたからちゃんと使えるはずなのだが、エラーが出てきてしまった。
原因を調べよう。
*Main Data.List Numeric> :t showHex
showHex :: (Integral a, Show a) => a -> ShowS
ということで、入力は1つなので、間違いはないはず。
もしかして、10進数の文字列に直すshowとは何か違うかもしれないので、確認しよう。
*Main Data.List Numeric> :t show
show :: Show a => a -> String
show はString が出てきているが、showHex は ShowS が出てくるのだ。
つまり、showHexは、showとは違うのだ。
では、ShowS型って何だろう。
*Main Data.List Numeric> :i ShowS
type ShowS = String -> String -- Defined in `GHC.Show'
haskell.orgの説明を見ると、
type ShowS = String -> StringSource
The shows functions return a function that prepends the output String to an existing String.
となっていた。showsの関数は、既に存在する文字列の前に付加されるらしいのだ。
それから、ちょっとネットで探して、結局、showHex は、16進数にする数値だけではなく、16進数になった文字列が前にくっつけられる文字を第2引数として加えないとダメなのだ。
要するに、
showHex :: (Integral a, Show a) => a -> String -> String
と考えてないといけない。
*Main Data.List Numeric> showHex 1000 ""
"3e8"
*Main Data.List Numeric> showHex 1000 "番地"
"3e8\30058\22320"
*Main Data.List Numeric> putStrLn (showHex 1000 "番地")
3e8番地
さて、これで、16進数に直す方法が分かった。
addhead xa@(x:_) = showHex (ord x) " " ++ xa
showHexの第2引数に ” ” を与えることで、16進数の後ろに2文字の空白文字がくっつくので、その後に漢字が並べば大丈夫だ。
それで実行してみると、こうなった。
*Main Data.List Numeric> putStrLn (take 100 unicodetable)
4e00 一丁丂七丄丅?万丈三上下丌不与?丐丑丒?且丕世丗丘丙????丞丟
4e20 ?両?丣两?並?丨?个丫?中丮丯丰丱串??丵丶?丸丹?主丼??丿
4e40 乀乁乂乃乄久?乇???之?乍乎乏
成功だ。あとは、unicodetable を書き出すだけ。
main = writeFile "UnicodeTable.txt" unicodetable
これでファイルがちゃんと書き出される。
長くなったので、unicodeTable.hsを用意した。
書き出したユニコード表 UnicodeTable.txt