2

haskellで複雑なパターンを一致させることは可能ですか?

つまり、カンマ区切り値(CSV)ファイルがあります。

name,ID,fieldA,fieldB

次のような関数を書くことは可能ですか?

getName (n:',':xs) = n

単一の要素でnはなくリストはどこにありますか?

4

4 に答える 4

6

1980年代に私が小さな男の子だったとき、私はそのスタイルで複雑なパターンを持つ関数型言語を実装しました。それはパターンで++を許可することになりました。結果のパターンはあいまいであったため、マッチングにはバックトラック検索プロセスが含まれていました。プログラマーは、++の左側のパターンに一致するプレフィックスの長さを最小化するか最大化するかを効果的に指定できました。この言語には「パターンガード」の形式があり、候補の一致をテストして、後続の計算が成功し、失敗した場合に拒否されるかどうかを確認できます。結果として得られたプログラムは、多くの場合、その意味について明白でした。とても楽しかった。

最近、そのような問題に直面したとき、私は手を差し伸べますspan、そしてそれがそれをカットしないならば、私はパーサーコンビネーターを使います。

span :: (a -> Bool) -> [a] -> ([a], [a])

spanは、述語pとリストxsに適用され、最初の要素がpを満たす要素のxsの最長の接頭辞(おそらく空)であり、2番目の要素がリストの残りであるタプルを返します。

したがって、特に、最初のコンマ(またはコンマがない場合は全体)の前にあるものと、残り(コンマがある場合はコンマで始まる)にspan (/= ',')分割されます。String

それでもうまくいかない場合は、パーサーコンビネーターを使用します。

しかし、私はいつもそれがいかに簡単だったかを覚えています。

于 2012-09-06T10:16:02.410 に答える
3

行を分割する関数を作成する必要があります...

import Data.List

parts = map tail . groupBy (/=) . (',':)

次に、アクセサ関数を簡単に記述できます。

getName xs = n where [n,_,_,_] = parts xs
getID   xs = i where [_,i,_,_] = parts xs
...

ただし、いつものように、データ型を使用すると便利です。

data Record = Record {getName :: String   
                     ,getId :: Int
                     ,getFieldA  
                     ,getFieldB :: String
                     } deriving Show 

initRecord xs = Record name (read id) fieldA fieldB where
                [name, id, fieldA, fieldB] = parts xs

もちろん、エラー処理が必要な場合は、もう少し難しくなります...

ところで、Haskell CSVライブラリがあります:http://hackage.haskell.org/packages/archive/csv/0.1.1/doc/html/Text-CSV.html

于 2012-09-06T10:38:28.680 に答える
2

splitOnfromのようなものを使用してからData.List.Split、リスト要素でパターンマッチを使用できます。

> splitOn "," "a,b,c,d"
["a","b","c","d"]

分割パッケージに入っています。

より複雑なものについては、Parsecを使用できます。

于 2012-09-06T10:37:39.943 に答える
1

うーん、よくわかりませんが、そうは思いません。あなたはおそらくあなたの問題に取り組むためにHaskellの正規表現について何かをチェックするべきです。

于 2012-09-06T10:09:00.033 に答える