2012-12-05 22 views
1

所以我有一些Haskell代碼,我想與Data.Set一起使用。基本上,因爲我沒有考慮太多的替代品,並且需要一個結構來存儲Ord的元素而沒有重複。mapM for Data.Set在Haskell

我現在已經到了一種情況,我想爲map.S爲Data.Set 之類的東西,以便我可以在設置單個元素上執行一元操作。 我已經搜索Hayoo的類型,如(a -> m b) -> Set a -> m (Set b),但沒有發現任何有用的東西。

我也查看了Data.Traversable只是爲了發現它具有[],Maybe和(Map k)的實例,但不適用於Set。

所以我的問題是:

  1. 爲什麼沒有MAPM爲坐落在在data.set?
  2. 是否已經有一個包提供了像我錯過的mapM的東西?
  3. 是不是希望通過集合映射M? (爲什麼有什麼辦法?)

回答

8

的主要問題是Traversable需要Functor,並設置不能函子,因爲他們需要一個Ord約束而仿函數必須是不受約束的。

但是,套件是可摺疊的,所以如果您不需要收集結果,則可以使用Data.Foldable中的mapM_

如果您確實需要結果,您可以通過列表(例如,

fromList <$> mapM f (toList s) 
+0

是的 - 我想通過列表來做,我只是希望有更好的解決方案。 –

+2

如果你的地圖函數不是單調的(即不滿足'x luqui

4

您可能會感興趣的lens包。它爲遍歷(在許多其他事物中)提供了更一般的抽象。雖然它並沒有解決具有高效mapMSet S的問題,它允許表達遍歷約束的數據類型:

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的文件說,這是受列出的融合。有一些運氣(取決於所討論的應用)中間列表可能會被融合掉。

+0

請注意,您的'setTraversal'不是合法的'Traversal'(這就是爲什麼['Data.Set.Lens'](http://hackage.haskell.org/packages/archive/lens/latest/doc /html/Data-Set-Lens.html)不會導出它)。特別是,它可以改變Set中的元素數量,這可以打破「遍歷」法則。 – shachaf

+0

@shachaf是的,的確如此。如果遍歷函數不是[內射](https://en.wikipedia.org/wiki/Injective_function),那麼結果將比原始元素少。 –