2

パーサーはより適切なエラーメッセージを生成する必要があるため、一部のコードをattoparsecからParsecに変換しています。attoparsecコードはinClass(およびnotInClass)を広範囲に使用します。inClass発生を機械的に変換できるParsecの同様の機能はありますか?HayooとHoogleは、この問題についての洞察を提供しませんでした。

inClass :: String -> Char -> Bool

inClass "a-c'-)0-3-"はと同等です\ x -> elem x "abc'()0123-"が、後者は非効率的で、広い範囲に書き込むのは面倒です。

他に何も利用できない場合は、自分で関数を再実装します。

4

2 に答える 2

2

いいえ、パーセクに相当するものはありません。あなたはそれを自分で書かなければなりません。2つの主なオプションがあります。

  1. 構文を解析して、inClass構文を作成しString、で使用しますoneOf
  2. それを解析して、渡す関数を作成しますsatisfy

前者はもちろん後者の特殊なケースであり、クラスの範囲が長い場合は効率が低下します。ただし、実装はおそらく少し簡単です。

(|||) :: (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

単純な可能性です。

于 2011-12-27T14:25:26.973 に答える
2

そのようなコンビネータはありません。存在する場合は、Text.Parsec.Char(関連するすべての標準パーサーコンビネーター関数Charが定義されている場所)にあります。かなり簡単に定義できるはずです。

ただし、アトパーセクがその実装で行うのと同じパフォーマンス上の利点を得ることができるとは思いません。FastSetこれは、8ビット文字でのみ機能する内部型に依存しています。もちろん、Unicodeサポートが必要ない場合、それは問題ではないかもしれませんが、のコードはFastSet、より大きい文字を渡すと予測できない結果が得られることを意味します。'\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

(ラムダから再帰を移動するように注意してください。GHCがこれを自分で実行できるかどうかはわかりません。)

于 2011-12-27T14:25:52.103 に答える