Q:

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?

A:

read (or rather, Text.Read.Lex.lexCharE) is how you get at GHC's internal table, which is defined as:
 lexEscChar =
   do c <- get
      case c of
        'a'  -> return '\a'
        'b'  -> return '\b'
        'f'  -> return '\f'
        'n'  -> return '\n'
        'r'  -> return '\r'
        't'  -> return '\t'
        'v'  -> return '\v'
        '\\' -> return '\\'
        '\"' -> return '\"'
        '\'' -> return '\''
        _    -> pfail

Eventually, you have to define the semantics somewhere.  You can do it in your program, or you can reuse GHC's.

A:

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.

