2016-05-23 11 views
1

Ich sehe, dass Parsec3 Text (nicht String) Eingang behandelt, so würde Ich mag einen alten String Parser konvertieren Textausgabe zu erhalten. Andere Bibliotheken, die ich verwende, verwenden auch Text, so dass die Anzahl der erforderlichen Konvertierungen reduziert würde.Parse Texteingabe und Textausgabe erhalten (nicht String) mit Parsec3

nun die parsec3 Bibliothek zu tun scheint, was es sagt (Griff sowohl Text und String Eingang), ist dieses Beispiel aus GCHI:

Text.Parsec.Text Text.Parsec Data.Text> parseTest (many1 $ char 's') (pack "sss") 
"sss" 
Text.Parsec.Text Text.Parsec Data.Text> parseTest (many1 $ char 's') "sss" 
"sss" 

Also, beide Text (erster Fall) und String (zweite Fall) funktioniert.

Nun In meinem realen, konvertiert Parser (sorry ich zusammen einige entfernte Teile des Codes hier, um Stück müssen ein vollständiges Beispiel zu machen)

{-# LANGUAGE OverloadedStrings #-} 
data UmeQueryPart = MidQuery Text Text MatchType 

data MatchType = Strict | Fuzzy deriving Show 

funcMT :: Text -> MatchType 
funcMT mt = case mt of 
     "~" -> Fuzzy 
     _ -> Strict 

midOfQuery :: Parser UmeQueryPart 
midOfQuery = do 
    spaces 
    string "MidOf" 
    spaces 
    char '(' 
    spaces 
    clabeltype <- many1 alphaNum 
    spaces 
    sep <- try(char ',') <|> char '~' 
    spaces 
    plabeltype <- many1 alphaNum 
    spaces 
    char ')' 
    spaces 
    return $ MidQuery (pack plabeltype) (pack clabeltype) (funcMT sep) 

finde ich mich mit einer Menge von Fehlern wie diese in Bezug auf die funcMT Anruf

UmeQueryParser.hs:456:96: 
    Couldn't match type ‘[Char]’ with ‘Text’ 
    Expected type: Text 
     Actual type: String 
    In the first argument of ‘funcMT’, namely ‘sep’ 
    In the fifth argument of ‘ midOfQuery’, namely ‘(funcMT sep)’ 

und wenn ich nicht explizit pack die Captures Text in dem Codebeispiel oben, dies:

UmeQueryParser.hs:288:26: 
    Couldn't match expected type ‘Text’ with actual type ‘[Char]’ 
    In the first argument of ‘ midOfQuery’, namely ‘(plabeltype)’ 
    In the second argument of ‘($)’, namely 
     ‘StartQuery (plabeltype) (clabeltype) (funcMT sep)’ 

So, es scheint, dass ich gefangene Strings explizit in in der Ausgabe konvertieren muss.

Also, warum muss ich durch einen Schritt von String oder Char-Text Umwandlung gehen, wenn der Punkt Text -> Text Parsing zu tun war?

Antwort

1

Sie können nur Ihre eigenen Text Parser machen, etwas Einfaches wie

midOfQuery :: Parser UmeQueryPart 
midOfQuery = do 
    spaces 
    lexeme $ string "MidOf" 
    lexeme $ char '(' 
    clabeltype <- lexeme alphaNums 
    sep <- lexeme $ try (char ',') <|> char '~' 
    plabeltype <- lexeme alphaNums 
    lexeme $ char ')' 
    return $ MidQuery plabeltype clabeltype (funcMT sep) 
    where 
    alphaNums = pack <$> many1 alphaNum 
    lexeme p = p <* spaces 

oder, etwas kompakter (aber ich denke immer noch besser lesbar):

midOfQuery :: Parser UmeQueryPart 
midOfQuery = spaces *> lexeme (string "MidOf") *> parens (toQuery <$> lexeme alphaNums <*> lexeme matchType <*> lexeme alphaNums) 
    where 
    lexeme :: Parser a -> Parser a 
    lexeme p = p <* spaces 

    alphaNums = pack <$> many1 alphaNum 

    parens = between (lexeme $ char '(') (lexeme $ char ')') 

    matchType = Fuzzy <$ char '~' <|> 
       Strict <$ char ',' 

    toQuery cLabelType sep pLabelType = MidQuery pLabelType cLabelType sep 
+0

'Nicht-Typ-Variable Argument in die Einschränkung: Stream sm Char (Verwenden Sie FlexibleContexts, um dies zuzulassen) Wenn Sie überprüfen, dass 'Lexeme' hat den abgeleiteten Typ Lexem :: Forall ASU (m :: * -> *). Stream s m Char => ParsecTsu ma -> ParsecT s u m a' –

+0

Ich kann es nicht lokal reproduzieren; Sie können jedoch "FlexibleContexts" aktivieren oder eine Typunterschrift "lexeme :: Parser a -> Parser a" eingeben. – Cactus

+0

Danke! Es scheint jetzt zu funktionieren. Danke, dass du mir geholfen hast zu sehen, dass der Parser vielleicht ein wenig kompakter ist als mein Beispiel. –