module Data.List.Ordered where
import Control.Lens (Iso', iso, Prism', prism')
import Control.Applicative
import Control.Comonad
import Data.Functor.Couple
import Data.Ord (comparing)
import Data.List (takeWhile, sort, sortBy, group)
import Data.Maybe
import Data.Semigroup
import Control.Monad
import qualified Data.Set as Set
import qualified Data.Map as Map
import Numeric.Natural
type Positive = Natural
#ifndef GHCI
instance Comonad Min where
extract (Min x) = x
duplicate (Min x) = Min (Min x)
instance Comonad Max where
extract (Max x) = x
duplicate (Max x) = Max (Max x)
#endif
newtype Ordered a = Ordered { getOrdered :: Map.Map a Positive }
deriving ()
instance (Ord a) => Eq (Ordered a) where
Ordered a == Ordered b = a == b
instance Ord a => Ord (Ordered a) where
Ordered a < Ordered b = a < b
map :: (Ord a, Ord b) => (a -> b) -> Ordered a -> Ordered b
map f (Ordered m) = Ordered (Map.mapKeys f m)
toList :: Ordered a -> [a]
toList (Ordered xs) = concatMap (uncurry $ flip $ replicate . fromIntegral) $ Map.toList xs
unsafeFromList :: Ord a => [a] -> Ordered a
unsafeFromList = fromMaybe (error "unsafeFromList: Not sorted") . fromList
fromList :: Ord a => [a] -> Maybe (Ordered a)
fromList xs
| xs /= sort xs = Nothing
| otherwise = Just $ Ordered $ Map.fromList $
Prelude.map (\x -> (head x, fromIntegral $ Prelude.length x)) $ group xs
ordered :: Ord a => Prism' [a] (Ordered a)
ordered = prism' toList fromList
unsafeOrdered :: Ord a => Iso' [a] (Ordered a)
unsafeOrdered = iso unsafeFromList toList
elem :: Ord a => a -> Ordered a -> Bool
elem k = (> 0) . occs k
occs :: Ord a => a -> Ordered a -> Int
occs k = maybe 0 fromIntegral . Map.lookup k . getOrdered
null :: Ordered k -> Bool
null = Map.null . getOrdered
length :: Ordered a -> Int
length = Prelude.length . toList