Haskell 与Parsec中的attorParsecs`inClass`等效

Haskell 与Parsec中的attorParsecs`inClass`等效,haskell,parsec,attoparsec,Haskell,Parsec,Attoparsec,我正在将一些代码从attoparsec翻译成Parsec,因为解析器需要生成更好的错误消息。ATOPASSEC代码广泛使用inClass(和notInClass)。Parsec是否有类似的功能,可以让我机械地翻译inClass-事件?Hayoo和Hoogle没有就此事提供任何见解 inClass :: String -> Char -> Bool inClass“a-c”-)0-3-”相当于\x->elem x“abc”()0123-“,但后者对于大范围编写效率低且繁琐 如果没有其

我正在将一些代码从attoparsec翻译成Parsec,因为解析器需要生成更好的错误消息。ATOPASSEC代码广泛使用
inClass
(和
notInClass
)。Parsec是否有类似的功能,可以让我机械地翻译
inClass
-事件?Hayoo和Hoogle没有就此事提供任何见解

inClass :: String -> Char -> Bool
inClass“a-c”-)0-3-”
相当于
\x->elem x“abc”()0123-“
,但后者对于大范围编写效率低且繁琐


如果没有其他可用的函数,我将自己重新实现该函数。

不,parsec中没有等效的函数。你必须自己写。我看到两个主要的选择

  • 解析
    inClass
    语法,从中创建一个
    字符串
    ,用于
    oneOf
  • 解析它以创建传递给
    满足的函数
  • 前者当然是后者的一个特例,如果你班上的射程更长,效率就会更低。但它可能更容易实现

    (|||) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
    p ||| q = \x -> p x || q x
    (&&&) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
    p &&& q = \x -> p x && q x
    
    parseClass (l:'-':h:more) = ((>= l) &&& (<= h)) ||| parseClass more
    parseClass (c:cs) = (== c) ||| parseClass cs
    parseClass [] = const False
    
    (a->Bool)->(a->Bool)->a->Bool
    p | | | q=\x->p x | | q x
    (&&&):(a->Bool)->(a->Bool)->a->Bool
    p&&q=\x->p x&&q x
    
    parseClass(l:'-':h:more)=((>=l)&&&&(没有任何这样的组合符;如果有,它将位于(这是所有涉及
    Char
    的标准解析器组合符函数的定义位置)。您应该能够相当容易地定义它

    不过,我不认为您能够获得attoparsec所具有的相同性能优势;它依赖于内部
    FastSet
    类型,该类型仅适用于8位字符。当然,如果您不需要Unicode支持,这可能不是一个问题,但这意味着您将通过大于'\255'
    ,因此,如果您想重用基于
    FastSet
    的解决方案,您至少必须读取正在解析的字符串。(您还必须将
    FastSet
    的实现复制到您的程序中,因为它没有导出…)

    如果您的范围字符串很短,那么像这样的简单解决方案可能会非常快:

    type Range = (Char, Char)
    
    inClass :: String -> Char -> Bool
    inClass = inClass' . parseClass
    
    parseClass :: String -> [Range]
    parseClass "" = []
    parseClass (a:'-':b:xs) = (a, b) : parseClass xs
    parseClass (x:xs) = (x, x) : parseClass xs
    
    inClass' :: [Range] -> Char -> Bool
    inClass' cls c = any (\(a,b) -> c >= a && c <= b) cls
    

    (注意将递归从lambda中移出;我不知道GHC是否能够/将自己做到这一点。)

    问题并不是真的需要解决,我可能会为此编写一个TH宏,但上面的代码很好地解决了这个问题。我想我会尽可能增加一些价值,因为“不,对不起”这对未来的访问者没有多大帮助:)
    inClass :: String -> Char -> Bool
    inClass "" = const False
    inClass (a:'-':b:xs) = \c -> (c >= a && c <= b) || f c where f = inClass xs
    inClass (x:xs) = \c -> c == x || f c where f = inClass xs