2014-05-06 95 views
3

我正在嘗試爲自定義文件格式創建解析器。在我與工作的格式,某些字段關閉標籤,像這樣:Parsec返回[Char]而不是文本

<SOL> 
<DATE>0517 
<YEAR>86 
</SOL> 

我試圖抓住</>之間的值,並把它作爲更大的解析器的一部分。

我已經拿出下面的代碼。麻煩的是,解析器返回[Char]而不是Text。我可以通過執行fmap pack $ return r來打包每個Char以獲得文本值,但我希望類型推斷可以使我無需執行此操作。有人可以暗示爲什麼我回來[Char]而不是Text,以及我如何可以取回Text而不必手動打包值?

{-# LANGUAGE NoMonomorphismRestriction #-} 
{-# LANGUAGE OverloadedStrings #-} 

import   Data.Text 
import   Text.Parsec 
import   Text.Parsec.Text 

-- |A closing tag is on its own line and is a "</" followed by some uppercase characters 
-- followed by some '>' 
closingTag = do 
    _ <- char '\n' 
    r <- between (string "</") (char '>') (many upper) 
    return r 

回答

4

string有型

string :: Stream s m Char => String -> ParsecT s u m String 

(見here對於文件)

因此得到一個String背面是什麼是應該發生的。

類型推斷不會改變類型,它只會推斷它們。 String是一個具體類型,所以無法推斷Text

可能做,如果你需要在這幾個地方,什麼是寫一個函數

text :: Stream s m Char => String -> ParsecT s u m Text 
text = fmap pack . string 

甚至

string' :: (IsString a, Stream s m Char) => String -> ParsecT s u m a 
string' = fmap fromString . string 

此外,它並不重要這個例子,但你可能想要導入Text合格,像pack這樣的名字在許多不同的模塊中使用。


由於與Orjan約翰森正確地指出,string實際上不是這裏的問題,many upper是。同樣的原則適用於此。

+2

我認爲'many upper'比'string'更有意義,因爲'between'只返回第三個解析器參數的結果。 –

+0

我看到'許多上層'的類型是'ParsecT sum [Char]' 我的印象是,如果OverloadedStrings擴展名可以用'[Char]'值作爲'Text'而不必手動打包它們打開了? – Arnob

+0

OverloadedString是一個語法擴展,而不是類型系統擴展。特別是,它將字符串文字(引號中的內容)讀入IsString類中。 – nomen

3

[Char]這裏的原因是,upper解析Charmany原來是成[Char]。我會寫我自己的組合子線沿線的:

manyPacked = fmap pack . many 

你很可能與類型類等類型級編程自動選擇manymanyPack之間取決於預期回報的類型,但我不認爲這是值得的。 (它可能看起來有點像Scala的CanBuiltFrom)。

相關問題