在Haskell中的Data.Set的mapM

时间:2012-12-05 18:57:43

标签: haskell

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

我现在遇到的情况是我希望有一些类似mapM for Data.Set的东西。 这样我就可以对一组单个元素执行monadic操作。 我已经在Hayoo搜索了(a -> m b) -> Set a -> m (Set b)这样的类型,但没有找到任何有用的内容。

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

所以我的问题是:

  1. 为什么Data.Set中没有为Map设置mapM?
  2. 是否已经有一个包裹可以提供我错过的mapM?
  3. 是否不鼓励想要将套装映射到套装上? (为什么和什么是替代品?)

2 个答案:

答案 0 :(得分:8)

主要问题是Traversable需要Functor,而且设置不能是仿函数,因为它们需要Ord约束而仿函数必须不受约束。

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

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

fromList <$> mapM f (toList s) 

答案 1 :(得分:4)

您可能对lens包感兴趣。它为遍历提供了更一般的抽象(在许多其他事情中)。虽然它没有解决mapM的高效Set问题,但它允许表达受约束数据类型的遍历:

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的文档说它受列表融合的影响。幸运的是(取决于所讨论的应用程序),中间列表可能会被融合掉。