私はHaskellを初めて使用し、現在、文字列の解析が必要な問題を解決しようとしています。入力文字列には、引用符で囲まれた単語のコンマ区切りリストが含まれています。この単一の文字列を文字列として単語のリストに解析したいと思います。そのような文字列の解析についてどこから始めればよいですか?役立つpartuclarモジュールや関数はありますか?
ps完全な解決策を投稿しないでください。出発点へのポインタを求めているので、その方法を学ぶことができます。
最も強力なソリューションは、パーサーコンビネーターです。Haskellにはこれらのいくつかがありますが、私の頭に浮かぶ最も重要なものは次のとおりです。
do
パーサーコンビネーターの大きな利点は、表記法(または必要Applicative
に応じてスタイル)を使用してパーサーを定義するのが非常に簡単なことです。
すばやく簡単な文字列操作機能が必要な場合は、文字列を操作するために必要な機能を提供するtext
ライブラリ(高性能のバイトエンコード文字列の場合)またはData.List
(通常のリストエンコード文字列の場合)を参照してください。
これは非常に単純な状況であるため、最終的に自分の解析関数をロールすることにしました。この質問を最初に投稿して以来、Haskellについて多くのことを学びました。ここで、解決策を文書化したいと思います。
split :: Char -> String -> [String]
split _ "" = []
split c s = firstWord : (split c rest)
where firstWord = takeWhile (/=c) s
rest = drop (length firstWord + 1) s
removeChar :: Char -> String -> String
removeChar _ [] = []
removeChar ch (c:cs)
| c == ch = removeChar ch cs
| otherwise = c:(removeChar ch cs)
main = do
handle <- openFile "input/names.txt" ReadMode
contents <- hGetContents handle
let names = sort (map (removeChar '"') (split ',' contents))
print names
hClose handle
先に進むための特に生意気な方法は次のとおりです。
parseCommaSepQuotedWords :: String -> [String]
parseCommaSepQuotedWords s = read ("[" ++ s ++ "]")
これはうまくいくかもしれませんが、それは非常に壊れやすく、かなりばかげています。基本的に、文字列のリストを書くHaskellの方法があなたの方法とほぼ一致するという事実を使用しているので、組み込みのRead
インスタンスはほとんどあなたが望むものです。より良いエラー報告のために使用することもできますreads
が、実際には、おそらく完全に別のことをしたいと思うでしょう。
一般的に、一見の価値があります-それは使うのが楽しいことであり、もともと私がHaskellparsec
に本当に興奮したことの1つです。しかし、自家製のソリューションが必要な場合は、とcase
の結果に関するステートメントを使用して簡単なことを書くことがよくspan
ありbreak
ます。入力で次のセミコロンを探しているとします。次に、break (== ';') inp
を返します(before, after)
。ここで、
before
inp
最初のセミコロン(またはセミコロンがない場合はすべて)までの内容です(含まれていません)。after
文字列の残りの部分です:
after
、最初の要素はセミコロンですbefore ++ after == inp
したがって、セミコロンで区切られたステートメントのリストを解析するには、次のようにします。
parseStmts :: String -> Maybe [Stmt]
parseStmts inp = case break (== ';') inp of
(before, _ : after) -> -- ...
-- ^ before is the first statement
-- ^ ignore the semicolon
-- ^ after is the rest of the string
(_, []) -> -- inp doesn't contain any semicolons
この質問に遭遇した人に完全な答えを与えるために、Data.Textにはいくつかの優れた機能もあります。
「実際の仕事」であるものにはパーセクを使用してください。
紹介については、https://therning.org/magnus/archives/tag/parsecをお読みください