11{-# LANGUAGE CPP #-}
22{-# LANGUAGE BangPatterns #-}
3+ {-# LANGUAGE LambdaCase #-}
34{-# LANGUAGE PatternGuards #-}
45#if __GLASGOW_HASKELL__
56{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}
@@ -294,6 +295,7 @@ type Size = Int
294295
295296#if __GLASGOW_HASKELL__ >= 708
296297type role Set nominal
298+ type role NonEmptySet nominal
297299#endif
298300
299301instance Ord a => Monoid (Set a ) where
@@ -384,30 +386,52 @@ setDataType = mkDataType "Data.Set.Internal.Set" [fromListConstr]
384386--------------------------------------------------------------------}
385387-- | /O(1)/. Is this the empty set?
386388null :: Set a -> Bool
387- null Tip = True
388- null (NE (Bin {})) = False
389+ null = \ case
390+ Tip -> True
391+ NE _ -> False
389392{-# INLINE null #-}
390393
391394-- | /O(1)/. The number of elements in the set.
392395size :: Set a -> Int
393- size Tip = 0
394- size (NE (Bin sz _ _ _)) = sz
396+ size = \ case
397+ Tip -> 0
398+ NE ne -> sizeNE ne
395399{-# INLINE size #-}
396400
401+ sizeNE :: NonEmptySet a -> Int
402+ sizeNE (Bin sz _ _ _) = sz
403+ {-# INLINE sizeNE #-}
404+
397405-- | /O(log n)/. Is the element in the set?
398406member :: Ord a => a -> Set a -> Bool
399- member = go
407+ member = fst . makeMember
408+
409+ memberNE :: Ord a => a -> NonEmptySet a -> Bool
410+ memberNE = snd . makeMember
411+
412+ makeMember
413+ :: Ord a
414+ => a
415+ -> ( Set a -> Bool
416+ , NonEmptySet a -> Bool
417+ )
418+ makeMember ! x = (go, go')
400419 where
401- go ! _ Tip = False
402- go x (NE (Bin _ y l r)) = case compare x y of
403- LT -> go x l
404- GT -> go x r
420+ go Tip = False
421+ go (NE ne) = go' ne
422+
423+ go' (Bin _ y l r) = case compare x y of
424+ LT -> go l
425+ GT -> go r
405426 EQ -> True
406427#if __GLASGOW_HASKELL__
407428{-# INLINABLE member #-}
429+ {-# INLINABLE memberNE #-}
408430#else
409431{-# INLINE member #-}
432+ {-# INLINE memberNE #-}
410433#endif
434+ {-# INLINE makeMember #-}
411435
412436-- | /O(log n)/. Is the element not in the set?
413437notMember :: Ord a => a -> Set a -> Bool
@@ -418,51 +442,95 @@ notMember a t = not $ member a t
418442{-# INLINE notMember #-}
419443#endif
420444
445+ notMemberNE :: Ord a => a -> NonEmptySet a -> Bool
446+ notMemberNE a t = not $ memberNE a t
447+ #if __GLASGOW_HASKELL__
448+ {-# INLINABLE notMemberNE #-}
449+ #else
450+ {-# INLINE notMemberNE #-}
451+ #endif
452+
421453-- | /O(log n)/. Find largest element smaller than the given one.
422454--
423455-- > lookupLT 3 (fromList [3, 5]) == Nothing
424456-- > lookupLT 5 (fromList [3, 5]) == Just 3
425457lookupLT :: Ord a => a -> Set a -> Maybe a
426- lookupLT = goNothing
458+ lookupLT = fst . makeLookupLT
459+
460+ lookupLTNE :: Ord a => a -> NonEmptySet a -> Maybe a
461+ lookupLTNE = snd . makeLookupLT
462+
463+ makeLookupLT
464+ :: Ord a
465+ => a
466+ -> ( Set a -> Maybe a
467+ , NonEmptySet a -> Maybe a
468+ )
469+ makeLookupLT ! x = (goNothing, goNothing')
427470 where
428- goNothing ! _ Tip = Nothing
429- goNothing x (NE (Bin _ y l r))
430- | x <= y = goNothing x l
431- | otherwise = goJust x y r
471+ goNothing Tip = Nothing
472+ goNothing (NE ne) = goNothing' ne
432473
433- goJust ! _ best Tip = Just best
434- goJust x best (NE (Bin _ y l r))
435- | x <= y = goJust x best l
436- | otherwise = goJust x y r
474+ goNothing' (Bin _ y l r)
475+ | x <= y = goNothing l
476+ | otherwise = goJust y r
477+
478+ goJust best Tip = Just best
479+ goJust best (NE ne) = goJust' best ne
480+
481+ goJust' best (Bin _ y l r)
482+ | x <= y = goJust best l
483+ | otherwise = goJust y r
437484
438485#if __GLASGOW_HASKELL__
439486{-# INLINABLE lookupLT #-}
487+ {-# INLINABLE lookupLTNE #-}
440488#else
441489{-# INLINE lookupLT #-}
490+ {-# INLINE lookupLTNE #-}
442491#endif
492+ {-# INLINE makeLookupLT #-}
443493
444494-- | /O(log n)/. Find smallest element greater than the given one.
445495--
446496-- > lookupGT 4 (fromList [3, 5]) == Just 5
447497-- > lookupGT 5 (fromList [3, 5]) == Nothing
448498lookupGT :: Ord a => a -> Set a -> Maybe a
449- lookupGT = goNothing
499+ lookupGT = fst . makeLookupGT
500+
501+ lookupGTNE :: Ord a => a -> NonEmptySet a -> Maybe a
502+ lookupGTNE = snd . makeLookupGT
503+
504+ makeLookupGT
505+ :: Ord a
506+ => a
507+ -> ( Set a -> Maybe a
508+ , NonEmptySet a -> Maybe a
509+ )
510+ makeLookupGT ! x = (goNothing, goNothing')
450511 where
451- goNothing ! _ Tip = Nothing
452- goNothing x (NE (Bin _ y l r))
453- | x < y = goJust x y l
454- | otherwise = goNothing x r
512+ goNothing Tip = Nothing
513+ goNothing (NE ne) = goNothing' ne
455514
456- goJust ! _ best Tip = Just best
457- goJust x best (NE (Bin _ y l r))
458- | x < y = goJust x y l
459- | otherwise = goJust x best r
515+ goNothing' (Bin _ y l r)
516+ | x < y = goJust y l
517+ | otherwise = goNothing r
518+
519+ goJust best Tip = Just best
520+ goJust best (NE ne) = goJust' best ne
521+
522+ goJust' best (Bin _ y l r)
523+ | x < y = goJust y l
524+ | otherwise = goJust best r
460525
461526#if __GLASGOW_HASKELL__
462527{-# INLINABLE lookupGT #-}
528+ {-# INLINABLE lookupGTNE #-}
463529#else
464530{-# INLINE lookupGT #-}
531+ {-# INLINE lookupGTNE #-}
465532#endif
533+ {-# INLINE makeLookupGT #-}
466534
467535-- | /O(log n)/. Find largest element smaller or equal to the given one.
468536--
@@ -526,9 +594,13 @@ empty = Tip
526594
527595-- | /O(1)/. Create a singleton set.
528596singleton :: a -> Set a
529- singleton x = NE $ Bin 1 x Tip Tip
597+ singleton = NE . singletonNE
530598{-# INLINE singleton #-}
531599
600+ singletonNE :: a -> NonEmptySet a
601+ singletonNE x = Bin 1 x Tip Tip
602+ {-# INLINE singletonNE #-}
603+
532604{- -------------------------------------------------------------------
533605 Insertion, Deletion
534606--------------------------------------------------------------------}
0 commit comments