2013-08-18 12 views
5

Sto cercando di imparare Parsec e sto cercando di analizzare un semplice indirizzo email. Ho provato il seguente codice. Il mio output previsto è l'intero indirizzo email sotto forma di stringa. Ma quando eseguo il codice, ottengo solo ".com" Potrebbe somene per favore dimmi cosa sta succedendo?Haskell Parsec woes

{-# LANGUAGE NoMonomorphismRestriction #-} 

import Text.Parsec 
import Control.Applicative hiding ((<|>)) 

email = many1 alphaNum 
    *> char '@' 
    *> many1 alphaNum 
    *> string ".com" 

emailstr = parse email "" "[email protected]" 

risposta

12

La firma tipo per *> dice che restituisce il risultato dalla seconda parser , e butta via il risultato dal primo parser . Pertanto, email restituisce solo il risultato dal parser finale nella sequenza.

Che probabilmente si desidera è qualcosa di più simile a

email = 
    stitch 
    <$> many1 alphaNum 
    <*> char '@' 
    <*> many1 alphaNum 
    <*> string ".com" 

Questo viene eseguito quattro parser e passa il risultato di ciascun come argomento di stitch. Se si scrive un'implementazione adatto per stitch:

stitch a b c d = a ++ [b] ++ C++ d 

allora si dovrebbe tornare stringa.

Si noti che a questo punto, si potrebbe anche mettere il nome utente e dominio in campi separati di una struttura di dati o qualcosa del genere:

data Email = Email {username, domain :: String} 

email = 
    Email 
    <$> many1 alphaNum 
    <* char '@' 
    <*> ((++) <$> many1 alphaNum <*> string ".com") 

Ora il parser restituisce un Email struttura piuttosto che una semplice stringa di pianura. Potrebbe non essere quello che cerchi, ma dimostra come scrivere un parser più sofisticato.

Tutto ciò sta utilizzando l'interfaccia Applicative a Parsec, che in genere è considerata di buon livello. L'altro modo di utilizzare Parsec è l'interfaccia Monad:

email = do 
    a <- many1 alphaNum 
    b <- char '@' 
    c <- many1 alphaNum 
    d <- string ".com" 
    return (a ++ [b] ++ C++ d) 
+0

È questo il modo idiomatico per realizzare tale compito? Non userò il codice in produzione da nessuna parte. Sto semplicemente cercando di imparare parsec. – Jay

+0

Entrambi i modi sono idiomatici – nponeccop