首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这个超级秒解析器在GHCi中工作,却不在源文件中编译?

为什么这个超级秒解析器在GHCi中工作,却不在源文件中编译?
EN

Stack Overflow用户
提问于 2021-02-23 00:01:49
回答 2查看 190关注 0票数 4

我是Haskell和Megaparsec库的初学者。在解析一行文本时,我需要解析行中的其余文本,直到行尾( LF或CRLF)。我的想法是使用somenoneOf,但即使在GHCi中进行测试之后,也无法编译代码,如下所示:

代码语言:javascript
复制
λ> import Data.Text (Text, pack)
λ> import Data.Void
λ> import Text.Megaparsec as M
λ> import Text.Megaparsec.Char as M
λ> import qualified Text.Megaparsec.Char.Lexer as L
λ> type Parser = Parsec Void Text
λ> 
λ> parse (some (noneOf "\r\n")) "" (pack "a line of text\r\n")
Right "a line of text"
λ> parse (some (noneOf "\r\n")) "" (pack "a line of text\n")
Right "a line of text"

因此,解析器(some (noneOf "\r\n"))成功编译并返回我预期的内容:“一行文本”,不包括行尾字符。但是,我无法在源文件中编译以下代码

代码语言:javascript
复制
pLineValue :: Parser Text
pLineValue = do
    str <- (some (noneOf "\r\n"))
    return (pack str)

编译器给出以下错误:

代码语言:javascript
复制
    • Ambiguous type variable ‘f0’ arising from a use of ‘noneOf’
      prevents the constraint ‘(Foldable f0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘f0’ should be.
      These potential instances exist:
        instance Foldable (Either a) -- Defined in ‘Data.Foldable’
        instance Foldable Maybe -- Defined in ‘Data.Foldable’
        instance Foldable ((,) a) -- Defined in ‘Data.Foldable’
        ...plus one other
        ...plus 37 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the first argument of ‘some’, namely ‘(noneOf "\r\n")’
      In a stmt of a 'do' block: str <- (some (noneOf "\r\n"))
      In the expression:
        do str <- (some (noneOf "\r\n"))
           return (pack str)
   |
78 |     str <- (some (noneOf "\r\n"))
   |                   ^^^^^^^^^^^^^

我做错了什么?源文件中正确的语法是什么?或者是否有更好的方法来解析剩余的文本直到但不包括LF或CRLF的结尾?我很感谢你的帮助,谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-23 18:45:50

noneOf接受任意Foldable容器:

代码语言:javascript
复制
noneOf :: (Foldable f, MonadParsec e s m) => f (Token s) -> m (Token s)

"\r\n"通常是String,它是Char的列表

代码语言:javascript
复制
> :t "\r\n"
"\r\n" :: [Char]

> :i String
type String = [Char]    -- Defined in ‘GHC.Base’

但是,如果启用了OverloadedStrings"\r\n"可以是任何IsString实例:

代码语言:javascript
复制
> :set -XOverloadedStrings
> :t "\r\n"
"\r\n" :: IsString p => p

因此,对noneOf的调用是模棱两可的,因为容器的类型没有固定下来:

代码语言:javascript
复制
> :t noneOf "\r\n"
noneOf "\r\n"
  :: (Foldable f, MonadParsec e s m,
      IsString (f (Token s))) =>
     m (Token s)

简单的解决方案是添加一个类型注释:

代码语言:javascript
复制
> :t noneOf ("\r\n" :: [Char])
noneOf ("\r\n" :: [Char])
  :: (MonadParsec e s m, Token s ~ Char) => m (Token s)

您可以使用任何Foldable-或Traversable-polymorphic函数(如maximumsum )来观察这一点。

或者,您可以使用显式列表代替:

代码语言:javascript
复制
> :t noneOf ['\r', '\n']
noneOf ['\r', '\n']
  :: (MonadParsec e s m, Token s ~ Char) => m (Token s)

但请注意,如果启用了OverloadedLists,则会出现同样的受约束类型问题:

代码语言:javascript
复制
> :set -XOverloadedLists
> :t noneOf ['\r', '\n']
noneOf ['\r', '\n']
  :: (Foldable f, MonadParsec e s m,
      IsList (f (Token s)),
      Item (f (Token s)) ~ Char) =>
     m (Token s)

如果您在源文件和GHCi之间遇到更多奇怪的差异,通常可以归结为GHCi为方便而使用的差异,例如“扩展的默认规则”,因此在这种情况下尝试:set -XNoExtendedDefaultRules:set -XExtendedDefaultRules有时会有所帮助。

票数 1
EN

Stack Overflow用户

发布于 2021-02-23 11:48:25

似乎你的一个符号并不来自你所期望的地方。但是,很难确切地知道问题出在哪里,因为您只给出了编译代码的一部分,而不是独立包含的代码。

https://stackoverflow.com/help/minimal-reproducible-example

正如Silvio的注释中所提到的,编译器似乎无法看到"\r\n"String对象,因此是Char的列表,因此是Foldable类的实例。

代码语言:javascript
复制
 λ> 
 λ> :type M.noneOf
M.noneOf
  :: (Foldable f, MonadParsec e s m) => f (Token s) -> m (Token s)
 λ> 

下面的代码非常相似,但是编译(并运行)非常完美:

代码语言:javascript
复制
import  Data.Text (Text, pack, unpack)
import  Data.Void
import  qualified  Text.Megaparsec  as  M

type MyParser = M.Parsec Void Text

pLineValue :: MyParser Text
pLineValue = do
    str <- (M.some (M.noneOf "\r\n"))
    return (pack str)


main :: IO ()
main = do
    let resT = M.parse pLineValue "-" (pack "a line of text\r\n")
        resS = case resT of
                 Right txt  ->  unpack txt
                 Left  _    ->  "ERROR"
    putStrLn $ "resS = " ++ resS
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66325206

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档