--- title: "Software Tools in Haskell: charfullwidth" subtitle: replace chars with fullwidth equivalents date: 2016-02-17 author: nbloomf tags: software-tools-in-haskell, literate-haskell --- As usual, we start with some imports. > -- sth-charfullwidth: replace characters with fullwidth equivalents > module Main where > > import System.Exit (exitSuccess) Replacing "normal" characters with fullwidth forms is much simpler. We reuse the structure of ``copy --char``, with a filter to map characters. > main :: IO () > main = do > charFilter (map toFullwidth) > exitSuccess And the map: > toFullwidth :: Char -> Char > toFullwidth = applyListMap full > where > full = > [ ('!','!'), ('"','"'), ('#','#'), ('$','$'), ('%','%') > , ('&','&'), ('\'','''), ('(','('), (')',')'), ('*','*') > , ('+','+'), (',',','), ('-','-'), ('.','.'), ('/','/') > , ('0','0'), ('1','1'), ('2','2'), ('3','3'), ('4','4') > , ('5','5'), ('6','6'), ('7','7'), ('8','8'), ('9','9') > , (':',':'), (';',';'), ('<','<'), ('=','='), ('>','>') > , ('?','?'), ('@','@'), ('A','A'), ('B','B'), ('C','C') > , ('D','D'), ('E','E'), ('F','F'), ('G','G'), ('H','H') > , ('I','I'), ('J','J'), ('K','K'), ('L','L'), ('M','M') > , ('N','N'), ('O','O'), ('P','P'), ('Q','Q'), ('R','R') > , ('S','S'), ('T','T'), ('U','U'), ('V','V'), ('W','W') > , ('X','X'), ('Y','Y'), ('Z','Z'), ('[','['), ('\\','\') > , (']',']'), ('^','^'), ('_','_'), ('`','`'), ('a','a') > , ('b','b'), ('c','c'), ('d','d'), ('e','e'), ('f','f') > , ('g','g'), ('h','h'), ('i','i'), ('j','j'), ('k','k') > , ('l','l'), ('m','m'), ('n','n'), ('o','o'), ('p','p') > , ('q','q'), ('r','r'), ('s','s'), ('t','t'), ('u','u') > , ('v','v'), ('w','w'), ('x','x'), ('y','y'), ('z','z') > , ('{','{'), ('|','|'), ('}','}'), ('~','~'), (' ',' ') > ] This probably looks terrible in your browser because unicode coverage. The ``applyListMap`` function treats a list of pairs like a mapping. > applyListMap :: (Eq a) => [(a,a)] -> a -> a > applyListMap zs x = case lookup x zs of > Nothing -> x > Just y -> y > > -- apply a map to stdin > charFilter :: (String -> String) -> IO () > charFilter f = do > xs <- getContents > putStr $ f xs