16進数文字列を得る関数 showHex


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

unicodetable4e00.png