2016-05-23 113 views
1

我看到,Parsec3處理Text(而不是String)輸入,所以我想轉換一箇舊的String解析器獲取文本輸出。我使用的其他庫也使用Text,這樣可以減少所需的轉換次數。現在解析文本輸入並獲得文本輸出(非字符串)與Parsec3

,該parsec3庫似乎做什麼它說(同時處理TextString輸入),這個例子是從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" 

所以,無論Text(第一種情況)和String(第二案例)的作品。現在

,在我的現實,轉換,解析器(抱歉,我不得不代碼的一些偏遠地區在這裏拼湊在一起,使一個完整的例子)

{-# 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) 

,我發現自己有很多像這樣的錯誤至於該funcMT呼叫

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)’ 

,如果我不明確pack的捕獲文本上面的代碼示例中,這樣的:

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)’ 

因此,我似乎需要明確地將捕獲的字符串轉換爲輸出中的Text

那麼,爲什麼我需要經過從StringChar轉換爲Text的步驟,當時要做Text -> Text解析?

回答

1

你可以只讓自己的Text解析器,一些簡單的像

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 

,或者稍微更緊湊的(但我認爲更可讀):在

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

'非類型變量參數約束:Stream sm Char (使用FlexibleContexts來允許此操作) 檢查'lexeme'是否具有推斷類型 lexeme :: forall asu(m :: * - > *)。 Stream s m Char => ParsecT s u m a - > ParsecT s u m a' –

+0

我無法在本地重現它;然而,你可以打開'FlexibleContexts'或者給它一個類型簽名'lexeme :: Parser a - Parser a'。 – Cactus

+0

謝謝!它現在似乎工作。感謝您幫助我發現解析器可能比我的示例更緊湊。 –