1

您将如何为 Data.Set 实现 catMaybes ?

我想出了:

import qualified Data.Set as Set
import qualified Data.Maybe as Maybe
setCatMaybes a = Set.map Maybe.fromJust . Set.delete Nothing $ a

fnord = Set.fromList [Nothing, Just 41, Just 43, Just 47]

然后我得到以下

setCatMaybes fnord == fromList [41,43,47]
4

4 回答 4

3

我认为您已经拥有的解决方案可能是最好的解决方案。按照约翰的解决方案,这里有一个相当短的解决方案:

setCatMaybes :: Ord a => Set.Set (Maybe a) -> Set.Set a
setCatMaybes s = Set.fromAscList [x | Just x <- Set.toAscList s]

或者这里有一个更长的,可能更快:

setCatMaybes2 :: Ord a => Set.Set (Maybe a) -> Set.Set a
setCatMaybes2 s
  | Set.null s = Set.empty
  | otherwise  = Set.mapMonotonic Maybe.fromJust $ case Set.deleteFindMin s of
                   (Nothing, s') ->  s'
                   _ -> s
于 2011-02-23T13:38:19.540 回答
3

既然Set (Maybe a)是这种怪异的类型,应用后才会出现f :: a -> Maybe b,那何不一石二鸟,造一个mapMaybeforData.Set呢?

import qualified Data.Set
import qualified Data.Maybe

mapMaybe :: Ord b => (a -> Maybe b) -> Data.Set.Set a -> Data.Set.Set b
mapMaybe f = Data.Set.fromList . Data.Maybe.mapMaybe f . Data.Set.toList

这样一来,怪事就Set (Maybe a)永远不存在了。

于 2011-10-06T15:00:38.013 回答
1
λ> foldr (\a b -> maybe b (`Set.insert` b) a) Set.empty fnord
fromList [41,43,47]

也适用于其他事情,所以可以做一个帮手:

catMaybesF :: Foldable f => (a -> f a -> f a) -> f a -> f (Maybe a) -> f a
catMaybesF insert emptyf = foldr (\a b -> maybe b (`insert` b) a) emptyf

catMaybesSet = catMaybesF Set.insert Set.empty
catMaybesSeq = catMaybesF (Seq.:<|) Seq.empty
于 2021-10-09T17:22:27.490 回答
0

这个怎么样:

setCatMaybes = Set.fromList . catMaybes

这将只需要遍历列表一次,就像Set.fromList一个好的消费者一样。

于 2011-02-23T11:41:21.667 回答