我想将两个Map实例与monadic函数联合起来。由于unionWith
类型签名,这成为一个问题:
unionWith :: Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
我正在寻找一种聪明的方法来做到这一点。这是我的天真实施:
monadicUnionWith :: (Monad m, Ord k) => (a -> a -> m a) -> Map k a -> Map k a -> m (Map k a)
monadicUnionWith f mapA mapB = do
let overlapping = toList $ intersectionWith (\a b -> (a,b)) mapA mapB
mergedOverlapping <- liftM fromList $ mapM helper overlapping
return $ union (union mergedOverlapping mapA) mapB
where
helper (k, (a,b)) = do
c <- f a b
return (k, c)
请注意union
有偏见
答案 0 :(得分:5)
不确定它是否更有效,但它有点凉爽(因为它涉及在地图中存储monadic值):
monadicUnionWith :: (Monad m, Ord k) => (a -> a -> m a) -> Map k a -> Map k a -> m (Map k a)
monadicUnionWith f mapA mapB =
Data.Traversable.sequence $ unionWith (\a b -> do {x <- a; y <- b; f x y}) (map return mapA) (map return mapB)
如果你想要,你可以使用
(\a b -> join (liftM2 f a b))
作为unionWith
的参数,甚至是
((join.).(liftM2 f))