2012-10-25 11 views
9

Czy ktoś może mi pomóc zrozumieć, jak używać stylu aplikacyjnego do pisania parserów Parse? Jest to kod mam:Parsek i styl aplkacji

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 

ale gdy próbuję go skompilować, otrzymuję następujący:

/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. 

Chodzi o to, że chcę cmdParse2 zrobić to samo, co cmdParse robi, ale za pomocą rzeczy aplikacyjne ... moje podejście jest prawdopodobnie całkowicie błędne, jestem nowy w firmie haskell

+0

Twój błąd jest jak gdyby napisane '(++) <$> ...' 'nie (:) <$> ...'. – huon

+0

Przepraszam, naprawiłem .. Próbowałem go z ++ i: i pomieszałem – Arg

+4

Najlepsze w dobrze zbadanych pytaniach, ponieważ odpowiedź brzmi: "Dobra robota, wybór dźwięku, zrobione poprawnie, ale napraw to drobny błąd typu . " +1 – AndrewC

Odpowiedz

4

Twoje zastosowanie aplikacji jest na miejscu, masz po prostu nieprawidłowy podpis. Spróbuj:

cmdParse2 :: Parsec String() String 
+1

głupi mnie, dzięki – Arg

+0

tylko szybkie pytanie, czy można uzyskać tekst z "wielu alfaNum"? więc nie zawsze pakuję go ręcznie, jeśli chcę używać tekstu zamiast ciągu? – Arg

+0

@Arg 1. Tak. Można konwertować: '(paczka <$> wiele ALPHANUM)', ale trzeba konwertować wszystko: 'cmdParse3 = cons <$> char '/' <*> (paczka <$> wiele ALPHANUM)', ale to lepiej napisane 'cmdParse4 = paczka <$> cmdParse2' , i może być lepiej, w zależności od aplikacji, aby opuścić go do końca i wykonaj 'pack <$> myTopLevelParser'. (Możesz również zainteresować się 'Text.Parsec.Text', aby zmienić także dane źródłowe.) 2. Dlaczego? Budujesz struny postaci na raz, łącząc je w dobry sposób. 'append' to _O (n) _ dla tekstu mimo to. – AndrewC

4

Twoje podejście wygląda dla mnie poprawnie, problem polega na tym, że cmdParse2 ma niewłaściwy typ. Powinien mieć ten sam typ co cmdParse. Nawiasem mówiąc, można pominąć parens wokół char '/' w parser styl aplikacji.

+0

fajne, dzięki za podpowiedź parens – Arg