没有任何这样的组合器;如果有,它将在Text.Parsec.Char中(其中定义了所有涉及的标准解析器组合器函数Char
)。您应该能够相当容易地定义它。
不过,我认为您无法获得与 attoparsec实现相同的性能优势;它依赖于内部FastSet
类型,该类型仅适用于 8 位字符。当然,如果您不需要 Unicode 支持,那可能不是问题,但代码FastSet
暗示您将通过 Chars 大于 获得不可预测的结果'\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
你甚至可以尝试这样的事情,它至少应该和上面的版本一样高效(包括当多次调用单个inClass s
的时候),另外还避免了列表遍历开销:
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
(注意将递归移出lambda;我不知道 GHC 是否可以/会自己这样做。)