HaskellのReadPを使用して、ファイル内の数字のリストに対して非常に単純なパーサーを行いました。それは動作しますが、非常に遅いです...このタイプのパーサーのこの通常の動作ですか、何か間違っていますか?HaskellのReadPの使用方法を修正しました。
答えて
import Text.ParserCombinators.ReadP
import qualified Data.IntSet as IntSet
import Data.Char
setsReader :: ReadP [ IntSet.IntSet ]
setsReader =
setReader `sepBy` (char '\n')
innocentWhitespace :: ReadP()
innocentWhitespace =
skipMany $ (char ' ') <++ (char '\t')
setReader :: ReadP IntSet.IntSet
setReader = do
innocentWhitespace
int_list <- integerReader `sepBy1` innocentWhitespace
innocentWhitespace
return $ IntSet.fromList int_list
integerReader :: ReadP Int
integerReader = do
digits <- many1 $ satisfy isDigit
return $ read digits
readClusters:: String -> IO [ IntSet.IntSet ]
readClusters filename = do
whole_file <- readFile filename
return $ (fst . last) $ readP_to_S setsReader whole_file
setReader
が数字の間の空白は、任意できるようにされているので、指数関数的挙動を有します。ラインのよう:
12 34 56
これらのパースを見ている:あなたは、これは長い行のために手に負えなくなる可能性がどのように見ることができました
[1,2,3,4,5,6]
[12,3,4,5,6]
[1,2,34,5,6]
[12,34,5,6]
[1,2,3,4,56]
[12,3,4,56]
[1,2,34,56]
[12,34,56]
。 ReadP
は、すべての長さの順に有効なパーズを返します。最後のパーズに到達するには、これらすべての中間パースを通過しなければなりません。変更:
int_list <- integerReader `sepBy1` innocentWhitespace
へ:
int_list <- integerReader `sepBy1` mandatoryWhitespace
mandatoryWhitespace
のに適した定義については、この指数関数的な振る舞いをスカッシュします。 parsecで使用される解析手法は、この種のエラーに対してより寛容です。これは、欲張りなので、特定のブランチで入力を消費すると、そのブランチにコミットされ、戻ってくることはありません(明示的に要求しない限り)。したがって、それが正しく12
を解析すると、それは解析されることはありません1 2
。もちろん、それはあなたの選択肢をどのような順序で述べるかが重要であることを意味します。私はいつも考えるべき痛みが少しあります。
また、私は使用します。
head [ x | (x,"") <- readP_to_S setsReader whole_file ]
を有効な全ファイルの解析を抽出するには、場合、それは非常に迅速にすべての入力を消費するが、その入力を解釈する百bazillionの方法がありました。あいまいさに気にしない場合は、最初のものが早く到着するため、最初のものを最後のものよりもむしろ返すでしょう。
今すぐご利用ください!ありがとう! – dsign
- 1. haskell ReadP(<++)関数の問題
- 2. ベストプラクティス:フライウェイ・マイグレーション・スクリプトを使用した後の修正方法
- 3. CygwinでHaskellコードをコンパイルし、Windows上のHaskellプラットフォームの他のバグを修正しました。
- 4. ASP.Net MVCでAutoMapperを使用する方法を修正しました
- 5. navbarの操作方法を修正しましたか?
- 6. .NET用ライブラリを修正しました
- 7. Google Survey APIを使用してBILLING_TRANSACTION_ERRORを修正しました
- 8. 「System.AggregateExceptionがmscorlib.dllで発生しました」の修正方法
- 9. OWASPを使用したJavaのクロスサイトスクリプティングの脆弱性を修正しました。
- 10. Anaconda Pythonの破損修正を修正しました。
- 11. PHPを使用してJSON形式を修正する方法
- 12. unicode.encode( 'rot13')を使用してUnicodeEncodingErrorを修正する方法
- 13. 修正ナビローリング使用時のカルーセル - bootrap NAV-修正トップを使用して
- 14. ワークステーションがクラッシュしました - SVNを修正する方法
- 15. RazorとMVC3を使用してwebgridのページャーメソッドのCSSを修正しました
- 16. jsの「スクリプトエラー」を修正しました
- 17. メニューのピクセルを修正しました
- 18. ReadPパーサーをデバッグする方法は?
- 19. ジャパンマッパーを使用するための依存関係を修正しました
- 20. 図の参照用のHTMLマークアップを修正しました
- 21. Python用のVS2015のインデントを修正しました
- 22. ApacheでURLの%のエスケープを正しく修正しました
- 23. Node.jsを使用して単純なデータを送信する方法を修正しました
- 24. S3の書式を使用したジェネリックスの修正
- 25. Pythonを使用した既存のワークブックの作成と修正
- 26. スクリプトを使用したElasticsearch multitypesクエリの不具合の修正
- 27. HTML、CSS、修正のヘッダーを使用したテーブル本体のスクロール
- 28. Haskellでコマンドライン引数を使って関数を修正するためのディスパッチ
- 29. haskellプロジェクトで「ワープ文字」の問題を修正する方法は?
- 30. Haskell正規表現ライブラリを使用した置換/置換
入力ファイルの大きさはどれくらいですか?私は病理学的に遅いものは見つけられませんが、setReaderに中間リストを使用させたくないかもしれませんし、入力のStringではなくByteStringのほうが良いかもしれません。また、Text.Read.LexモジュールにReadP整数パーサーのreadIntPがあります。これは、integerReaderよりもパフォーマンスが向上する可能性があります。 –
ヘルプスティーブンに感謝します。 ReadPを使ったのは初めてのことですが、私はText.Read.Lexについて知りませんでした。 – dsign