2010-08-24 17 views
2

J'écris un analyseur parsec qui se lit dans les chaînes et convertit les caractères évadés, dans le cadre de l'exercice 3 here.Haskell: caractère Echappé de caractère

Pour cet exercice, je me sers de cette fonction:

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

Je ne suis pas à impressionné par l'utilisation de read pour convertir le caractère x dans le caractère d'échappement avec le nom x. Quelqu'un peut-il suggérer une fonction plus élégante du type Char -> Char pour ce faire?

Répondre

5

Une façon est d'établir les cas limitativement:

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

Vous pouvez également utiliser 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 

Le bit fromJust peut paraître étrange. Le type de lookup est

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

ce qui signifie que pour une valeur d'un certain type sur lequel l'égalité est définie et une table de consultation, il veut vous donner la valeur correspondante de la table de recherche, mais la clé n'est pas garanti être présent dans la table! Tel est l'objet de Maybe, dont la définition est

data Maybe a = Just a | Nothing 

Avec fromJust, il suppose obtenu Just something (-à-dire, c a une entrée dans escapes), mais cela se désagréger lorsque cette hypothèse est invalide:

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

Ces exemples vous déplacer le long de l'exercice, mais il est clair que vous souhaitez une meilleure gestion des erreurs. En outre, si vous vous attendez à ce que la table de recherche soit grande, vous pouvez rechercher Data.Map.

1

Je viens de modèle utilisé correspondant pour les quelques échappées je pris soin de - à savoir 't' -> '\t' etc. La solution d'autres lecteurs ont suggéré étaient similaires. Pas très générique, mais très simple.

6

read (ou plutôt, Text.Read.Lex.lexCharE) est de savoir comment vous obtenez à GHC's internal table, qui est défini comme:

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 

Finalement, vous devez définir la sémantique quelque part. Vous pouvez le faire dans votre programme, ou vous pouvez réutiliser GHC.

+0

Il est dommage que 'lexEscChar' ne soit pas exporté sinon cela aurait été la réponse parfaite. Merci de m'avoir mis au courant. – dukedave