mapM for Data.Set in Haskell



所以我有一些Haskell代码,我想在其中使用Data.Set。基本上是因为我没有过多地研究替代方案,并且需要一个结构来存储 Ord 的元素而没有重复项。

我现在已经到了想要像mapM for Data.Set这样的东西的情况。这样我就可以对集合的各个元素执行一元运算。我已经在 Hayoo 中搜索了类似 (a -> m b) -> Set a -> m (Set b) 的类型,但没有找到任何有用的东西。

我还调查了Data.Traversable,只是为了发现它有 []、也许和 (Map k) 的实例,但没有 Set 的实例。

所以我的问题是:

  1. 为什么 Data.Set 中没有 Set的 mapM?
  2. 是否已经有一个软件包可以提供我错过的类似 mapM 的东西?
  3. 是否不鼓励在集合上映射M?(为什么以及什么是替代方案?

主要问题是Traversable需要Functor,集合不能是函子,因为它们需要Ord约束,而函子必须是不受约束的。

但是,套装是可折叠的,因此如果您不需要收集结果,则可以使用 Data.Foldable 中的mapM_

如果您确实需要结果,您可以通过列表,例如

fromList <$> mapM f (toList s) 

您可能对镜头包感兴趣。它为遍历(以及许多其他内容)提供了更一般的抽象。虽然它不能解决为Set提供有效mapM的问题,但它允许表达受约束数据类型的遍历:

import Control.Lens.Traversal
import Data.Traversable (traverse)
import Data.Set (Set)
import qualified Data.Set as Set
-- forall f. Applicative f => (a -> f b) -> Set a -> f (Set b)
setTraversal :: (Ord b) => Traversal (Set a) (Set b) a b
setTraversal f = (fmap Set.fromList) . traverse f . Set.toList
main = do
    print $ mapMOf setTraversal (x -> [x+1, x-1]) $ Set.fromList [0, 10, 20]

请注意,Set.toList的文档说它受列表融合的影响。如果运气好的话(取决于所讨论的应用),中间列表可能会被融合掉。

最新更新