所以我有一些Haskell代码,我希望与Data.Set
一起使用。
基本上是因为我没有太多地研究替代方案,并且需要一个结构来存储Ord的元素而没有重复。
我现在遇到的情况是我希望有一些类似mapM for Data.Set的东西。
这样我就可以对一组单个元素执行monadic操作。
我已经在Hayoo搜索了(a -> m b) -> Set a -> m (Set b)
这样的类型,但没有找到任何有用的内容。
我也调查Data.Traversable
只是为了发现它有[],Maybe和(Map k)的实例,但不是Set的实例。
所以我的问题是:
答案 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
的文档说它受列表融合的影响。幸运的是(取决于所讨论的应用程序),中间列表可能会被融合掉。