最近我多次遇到这种模式。基本上它会处理as
中bs
中也存在的所有键,并且不会触及其他键。
foo :: (a -> b -> a) -> Map a -> Map b -> Map a
foo f as bs = (Map.intersectionWith f as bs) `Map.union` (Map.difference as bs)
由于union
的性质,这可以缩短为:
bar :: (a -> b -> a) -> Map a -> Map b -> Map a
bar f as bs = Map.intersectionWith f as bs `Map.union` as
但是这仍需要三次遍历(两次超过as
一次超过bs
)。我的直觉是应该有一种方法可以通过两次遍历来解决这个问题。
答案 0 :(得分:6)
实际上它就在那里:Map.differenceWith
做对了我想要的。这有点不直观,但基本上它需要as
和bs
的实际差异,而可以将交叉点中的值包含在结果集中。
因此这个
foo :: (a -> b -> a) -> Map a -> Map b -> Map a
foo f as bs = (Map.intersectionWith f as bs) `Map.union` (Map.difference as bs)
可以改写为
baz :: (a -> b -> a) -> Map a -> Map b -> Map a
baz f as bs = Map.differenceWith (\a b -> Just (f a b)) as bs
简单...抱歉浪费你的时间:)。