Skip to content

Commit 9555fb4

Browse files
committed
WIP: NonEmptySet functions
1 parent c99b359 commit 9555fb4

File tree

1 file changed

+100
-28
lines changed

1 file changed

+100
-28
lines changed

containers/src/Data/Set/Internal.hs

Lines changed: 100 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
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
296297
type role Set nominal
298+
type role NonEmptySet nominal
297299
#endif
298300

299301
instance 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?
386388
null :: 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.
392395
size :: 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?
398406
member :: 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?
413437
notMember :: 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
425457
lookupLT :: 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
448498
lookupGT :: 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.
528596
singleton :: 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

Comments
 (0)