0

マップとそのコンテンツを簡単に更新できるため、命令型言語で簡単なHaskellでの変換をどのように実装しますか?

while( line = next()) {
  Data d = parse(line);
  if( map.get(d.key) == null) map.put(d.info);
  else map.get(d.key).update(d.info);
}

for(d : map.values) print d.computeResult()

(単純化しすぎた)具体的な例を挙げると、入力には、何らかのルールによって関連付ける必要がある行が含まれます。ここで、プログラムは、キー 'k' の下の値が追加、更新され、最終的には削除され、出力に表示されないことを検出する必要があります。

[time] ADD key=k, value1=V1
[time] ADD key=k, value2=V2
[time] ADD key=k, value1=ABC
[time] [...]
[time] DEL key=k
[time] ADD key=k2, value1=V1

レンズの使用、モナドの状態、キーによるデータの並べ替え (可能であれば) などを検討する必要がありますか? これを実装する最もクリーンな方法はどれですか? このような Haskell スクリプトは、たとえば awk/sed/grep/xmlstartlet スープよりも維持しやすいかどうか疑問に思っています。

4

1 に答える 1

5

insert :: Ord k => k -> a -> Map k a -> Map k afromData.Mapはまさにあなたが望むことをします。

import qualified Data.Map as M

addLines :: [String] -> M.Map Int String
addLines = foldr (uncurry M.insert) M.empty . parseLines
    where parseLines :: [String] -> [(Int, String)]
          parseLines = zip [1..]

addLinesMapは保存する行のリストを受け取り、行のキーとして行番号を含む を返します。大量のテキストを に丸呑みしただけの場合はString、 を使用lines :: String -> [String]して行に分割します。

コメントでガブリエルが示唆しているように、行のリストをに変換するより良い方法Map

addLines = M.fromList . zip [1..]

注: 最初の関数では のMap代わりにイニシャルを渡すことができますM.emptyが、 を使用M.unionして s を 2 番目の関数と組み合わせるMapと、おそらく高速になります。

于 2013-07-19T22:44:58.243 に答える