Search code examples
haskellcharescaping

Haskell: Escaped character from character


I'm writing a parsec parser which reads in strings and converts escaped characters, as part of exercise 3 here.

For that exercise I am using this function:

escapedCharFromChar :: Char -> Char
escapedCharFromChar c = read $ concat ["'\\",[c],"'"]

I am not to impressed with the use of read to convert the character x into the escape character with the name x. Can anyone suggest a more elegant function of type Char -> Char to do this?


Solution

  • One way is to lay out the cases exhaustively:

    charFromEscape :: Char -> Char
    charFromEscape 'n' = '\n'
    charFromEscape 't' = '\t'
    --- ... --- Help!
    

    You could also use lookup:

    -- this import goes at the top of your source file
    import Data.Maybe (fromJust)
    
    charFromEscape :: Char -> Char
    charFromEscape c = fromJust $ lookup c escapes
      where escapes = [('n', '\n'), ('t', '\t')] -- and so on
    

    The fromJust bit may look strange. The type of lookup is

    lookup :: (Eq a) => a -> [(a, b)] -> Maybe b
    

    which means for a value of some type over which equality is defined and a lookup table, it wants to give you the corresponding value from the lookup table—but your key isn't guaranteed to be present in the table! That's the purpose of Maybe, whose definition is

    data Maybe a = Just a | Nothing
    

    With fromJust, it assumes you got Just something (i.e., c has an entry in escapes), but this will fall apart when that assumption is invalid:

    ghci> charFromEscape 'r'
    *** Exception: Maybe.fromJust: Nothing

    These examples will move you along in the exercise, but it's clear that you'd like better error handling. Also, if you expect the lookup table to be large, you may want to look at Data.Map.