入力された文字列の英数字を全角から半角に変換したい場合があります。
Haskell の内部コードは UCS4 が使用されています。UCS4 では ASCII の文字は1バイト文字列と同じ順序で領域が割り当てられています。それに対応する全角文字は 0xff01 から割り当てられています。
(SPACE は ASCII:0x20 JIS X 0208:0x3000)
-- ASCII hanSpaceChar = chr 0x20 han = map chr [0x21..0x7e] -- !"#$%・・略・xyz{|}~ -- ASCIIの全角に該当する文字 zenSpaceChar = chr 0x3000 zen = map chr [0xff01..0xff5e] -- !釤#$%・・略・xyz{|}〜
並んでいる順序が同じですから、その差 0xfee0 を足したり引いたりすれば簡単に全角、半角を変換できるのです。
import Data.Char import Numeric han = map chr [0x21..0x7e] zen = map chr [0xff01..0xff5e] zenSpace = ' ' toZenChar :: Char -> Char toZenChar c = chr (ord c + 0xfee0) toHanChar :: Char -> Char toHanChar c = chr (ord c - 0xfee0) zenToHan :: String -> String zenToHan [] = [] zenToHan (c:cs) = if ord c >= 0xff01 && ord c <= 0xff5e then toHanChar c : zenToHan cs else c:zenToHan cs zenSpToHanSp :: String -> String zenSpToHanSp [] = [] zenSpToHanSp (c:cs) = if c == zenSpace then ' ' : zenSpToHanSp cs else c:zenToHan cs hanToZen :: String -> String hanToZen [] = [] hanToZen (c:cs) = if ord c >= 0x21 && ord c <= 0x7e then toZenChar c : hanToZen cs else c:hanToZen cs hanSpToZenSp :: String -> String hanSpToZenSp [] = [] hanSpToZenSp (c:cs) = if c == ' ' then zenSpace : hanSpToZenSp cs else c : hanSpToZenSp cs main = do -- 半角の隣に対応する全角を表示してみる。 -- 同じ順序で割り当てられているのが確認できる。 putStrLn $ concat $ map (\(han,zen)->[han,zen]) $ zip han zen -- => !!"釤##$$%%&&'釻(())**++,,-−.. -- //00112233445566778899::;;<<==>>?? -- @@AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ -- [[\\]]^^__``aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuu -- vvwwxxyyzz{{||}}~〜 -- 半角を全角に変換して表示 putStrLn $ hanToZen han -- => !釤#$%&釻()*+,−./0123456789:;<=>? -- @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] -- ^_`abcdefghijklmnopqrstuvwxyz{|}〜 -- 全角を半角に変換して表示 putStrLn $ zenToHan zen -- => !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] -- ^_`abcdefghijklmnopqrstuvwxyz{|}~
半角カナ、全角カナの変換も同様にやろうとしたが同じ順序に並んでいなかった・・・Orz