0

如何在 Haskell 中实现一种在命令式语言中很简单的转换,因为它可以轻松更新 map 及其内容?

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..]

addLines获取要存储的行列表,返回 aMap行号作为行的键。如果您只是将一堆文本啜饮成String,请使用lines :: String -> [String]将其分成几行。

正如 Gabriel 在评论中所建议的那样,将行列表转换为 a 的更好方法Map

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

注意:第一个函数允许你传入一个初始Map值而不是M.empty,但是使用M.unionto combine Maps 和第二个函数可能会更快。

于 2013-07-19T22:44:58.243 回答