2012-10-25 19 views
9

qualcuno può aiutarmi a capire come utilizzare lo stile applicativo per la scrittura di parser parsec? Questo è il codice che ho:Parsec e stile applicativo

module Main where 
import Control.Applicative hiding (many) 
import Text.Parsec 
import Data.Functor.Identity 
data Cmd = A | B deriving (Show) 

main = do 
    line <- getContents 
    putStrLn . show $ parseCmd line 

parseCmd :: String -> Either ParseError String 
parseCmd input = parse cmdParse "(parser)" input 

cmdParse :: Parsec String() String 
cmdParse = do 
    slash <- char '/' 
    whatever <- many alphaNum 
    return (slash:whatever) 

cmdParse2 :: String -> Parsec String() String 
cmdParse2 = (:) <$> (char '/') <*> many alphaNum 

ma quando provo a compilare, ottengo seguendo:

/home/tomasherman/Desktop/funinthesun.hs:21:13: 
    Couldn't match expected type `Parsec String() String' 
       with actual type `[a0]' 
    Expected type: a0 -> [a0] -> Parsec String() String 
     Actual type: a0 -> [a0] -> [a0] 
    In the first argument of `(<$>)', namely `(:)' 
    In the first argument of `(<*>)', namely `(:) <$> (char '/')' 
Failed, modules loaded: none. 

L'idea è che voglio cmdParse2 fare stessa cosa che cmdParse fa, ma utilizzando roba applicativa ... il mio approccio è probabilmente completamente sbagliato, sono nuovo di haskell

+0

Il tuo errore è come se tu avessi scritto '(++) <$> ...' 'non (:) <$> ...'. – huon

+0

scusate, risolto .. lo stavo provando sia con ++ che con: e ho risolto il problema con – Arg

+4

Il massimo in domande ben studiate, perché la risposta è "Ben fatto, scelta del suono, eseguita correttamente, ma correggere questo errore di tipo secondario ". +1 – AndrewC

risposta

4

L'utilizzo dell'applicativo è corretto, la firma è errata. Prova:

cmdParse2 :: Parsec String() String 
+1

stupido, grazie – Arg

+0

solo una domanda veloce, è possibile ottenere il testo di testo da 'molti alphaNum'? quindi non lo compro sempre manualmente se voglio usare Text invece di String? – Arg

+0

@Arg 1. Sì. È possibile convertire: '(pack <$> molti alphaNum)', ma è necessario convertire tutto: 'cmdParse3 = cons <$> char '/' <*> (pacchetto <$> molti alphaNum)' ma è meglio scrivere 'cmdParse4 = pacchetto <$> cmdParse2' e potrebbe essere meglio, a seconda dell'applicazione, lasciarlo fino alla fine e fare 'pack <$> myTopLevelParser'. (Potrebbe essere interessato anche a 'Text.Parsec.Text' per modificare anche i dati di origine.) 2. Perché? Stai costruendo le corde un personaggio alla volta, combinandole nel modo migliore. 'append' è _O (n) _ per Text comunque. – AndrewC

4

Il tuo approccio mi sembra corretto, il problema è che cmdParse2 ha il tipo sbagliato. Dovrebbe avere lo stesso tipo di cmdParse. A proposito, puoi omettere i paren intorno a char '/' nel parser di stile applicativo.

+0

cool, grazie per il suggerimento parents – Arg