{-# LANGUAGE CPP #-}
{-# LANGUAGE Safe #-}
module Relude.Nub
( hashNub
, ordNub
#if __GLASGOW_HASKELL__ > 804
, ordNubOn
, intNub
, intNubOn
#endif
, sortNub
, unstableNub
) where
import Data.Eq (Eq)
import Data.Hashable (Hashable)
import Data.HashSet as HashSet
import Data.Ord (Ord)
import Prelude (Int, (.))
import qualified Data.Set as Set
#if __GLASGOW_HASKELL__ > 804
import qualified Data.Containers.ListUtils as Containers
#endif
ordNub :: forall a . (Ord a) => [a] -> [a]
#if __GLASGOW_HASKELL__ > 804
ordNub :: [a] -> [a]
ordNub = [a] -> [a]
forall a. Ord a => [a] -> [a]
Containers.nubOrd
{-# INLINE ordNub #-}
#else
ordNub = go Set.empty
where
go :: Set.Set a -> [a] -> [a]
go _ [] = []
go s (x:xs) =
if x `Set.member` s
then go s xs
else x : go (Set.insert x s) xs
{-# INLINEABLE ordNub #-}
#endif
#if __GLASGOW_HASKELL__ > 804
ordNubOn :: forall b a . (Ord b) => (a -> b) -> [a] -> [a]
ordNubOn :: (a -> b) -> [a] -> [a]
ordNubOn = (a -> b) -> [a] -> [a]
forall b a. Ord b => (a -> b) -> [a] -> [a]
Containers.nubOrdOn
{-# INLINE ordNubOn #-}
#endif
hashNub :: forall a . (Eq a, Hashable a) => [a] -> [a]
hashNub :: [a] -> [a]
hashNub = HashSet a -> [a] -> [a]
go HashSet a
forall a. HashSet a
HashSet.empty
where
go :: HashSet.HashSet a -> [a] -> [a]
go :: HashSet a -> [a] -> [a]
go HashSet a
_ [] = []
go HashSet a
s (a
x:[a]
xs) =
if a
x a -> HashSet a -> Bool
forall a. (Eq a, Hashable a) => a -> HashSet a -> Bool
`HashSet.member` HashSet a
s
then HashSet a -> [a] -> [a]
go HashSet a
s [a]
xs
else a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: HashSet a -> [a] -> [a]
go (a -> HashSet a -> HashSet a
forall a. (Eq a, Hashable a) => a -> HashSet a -> HashSet a
HashSet.insert a
x HashSet a
s) [a]
xs
{-# INLINEABLE hashNub #-}
sortNub :: (Ord a) => [a] -> [a]
sortNub :: [a] -> [a]
sortNub = Set a -> [a]
forall a. Set a -> [a]
Set.toList (Set a -> [a]) -> ([a] -> Set a) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Set a
forall a. Ord a => [a] -> Set a
Set.fromList
{-# INLINE sortNub #-}
unstableNub :: (Eq a, Hashable a) => [a] -> [a]
unstableNub :: [a] -> [a]
unstableNub = HashSet a -> [a]
forall a. HashSet a -> [a]
HashSet.toList (HashSet a -> [a]) -> ([a] -> HashSet a) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> HashSet a
forall a. (Eq a, Hashable a) => [a] -> HashSet a
HashSet.fromList
{-# INLINE unstableNub #-}
#if __GLASGOW_HASKELL__ > 804
intNub :: [Int] -> [Int]
intNub :: [Int] -> [Int]
intNub = [Int] -> [Int]
Containers.nubInt
{-# INLINE intNub #-}
intNubOn :: (a -> Int) -> [a] -> [a]
intNubOn :: (a -> Int) -> [a] -> [a]
intNubOn = (a -> Int) -> [a] -> [a]
forall a. (a -> Int) -> [a] -> [a]
Containers.nubIntOn
{-# INLINE intNubOn #-}
#endif