yaya-containers-1.0.0.0: src/Yaya/Containers/Pattern/Map.hs
{-# LANGUAGE Safe #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Yaya.Containers.Pattern.Map
( Map (Bin, Tip),
-- | @since 0.1.2.0
eqMap,
-- | @since 0.1.2.0
compareMap,
-- | @since 0.1.2.0
readMapPrec,
-- | @since 0.1.2.0
showsMapPrec,
)
where
import "base" Control.Applicative ((*>), (<*>), (<|>))
import "base" Control.Category ((.))
import "base" Data.Bool (Bool (False, True), (&&))
import "base" Data.Eq (Eq, (==))
import "base" Data.Foldable (Foldable)
import "base" Data.Function (($))
import "base" Data.Functor (Functor, (<$), (<$>))
import "base" Data.Functor.Classes
( Eq1,
Eq2,
Ord1,
Ord2,
Read1,
Read2,
Show1,
Show2,
liftCompare,
liftCompare2,
liftEq,
liftEq2,
liftReadPrec,
liftReadPrec2,
liftShowsPrec,
liftShowsPrec2,
)
import "base" Data.Int (Int)
import "base" Data.Ord (Ord, Ordering (EQ, GT, LT), compare, (<=))
import "base" Data.Semigroup ((<>))
import "base" Data.Traversable (Traversable)
import qualified "base" Data.Tuple as Tuple
import "base" GHC.Generics (Generic, Generic1)
import "base" GHC.Read (expectP)
import "base" Text.Read
( Read,
ReadPrec,
parens,
prec,
readListPrec,
readPrec,
step,
)
import qualified "base" Text.Read.Lex as Lex
import "base" Text.Show
( Show,
ShowS,
showList,
showParen,
showString,
showsPrec,
)
import qualified "containers" Data.Map.Internal as Map
import "yaya" Yaya.Fold
( Projectable,
Recursive,
Steppable,
cata,
embed,
project,
)
import qualified "yaya-unsafe" Yaya.Unsafe.Fold as Unsafe
import "base" Prelude ((+))
data Map k v r = Tip | Bin Map.Size k ~v r r
deriving stock
( Eq,
Ord,
Generic,
-- | @since 0.1.2.0
Read,
Show,
Foldable,
Functor,
Generic1,
Traversable
)
instance Projectable (->) (Map.Map k v) (Map k v) where
project Map.Tip = Tip
project (Map.Bin size k v l r) = Bin size k v l r
instance Recursive (->) (Map.Map k v) (Map k v) where
cata = Unsafe.unsafeCata
instance Steppable (->) (Map.Map k v) (Map k v) where
embed Tip = Map.Tip
embed (Bin size k v l r) = Map.Bin size k v l r
eqMap ::
(k -> k' -> Bool) ->
(v -> v' -> Bool) ->
(r -> r' -> Bool) ->
Map k v r ->
Map k' v' r' ->
Bool
eqMap eqK eqV eqR = Tuple.curry $ \case
(Tip, Tip) -> True
(Bin size k v l r, Bin size' k' v' l' r') ->
size == size' && eqK k k' && eqV v v' && eqR l l' && eqR r r'
(_, _) -> False
compareMap ::
(k -> k' -> Ordering) ->
(v -> v' -> Ordering) ->
(r -> r' -> Ordering) ->
Map k v r ->
Map k' v' r' ->
Ordering
compareMap compareK compareV compareR = Tuple.curry $ \case
(Tip, Tip) -> EQ
(Tip, Bin {}) -> LT
(Bin {}, Tip) -> GT
(Bin size k v l r, Bin size' k' v' l' r') ->
compare size size'
<> compareK k k'
<> compareV v v'
<> compareR l l'
<> compareR r r'
readMapPrec :: ReadPrec k -> ReadPrec v -> ReadPrec r -> ReadPrec (Map k v r)
readMapPrec readPrecK readPrecV readPrecR =
let appPrec = 10
in parens . prec appPrec $
Tip
<$ expectP (Lex.Ident "Tip")
<|> expectP (Lex.Ident "Bin")
*> ( Bin
<$> step readPrec
<*> step readPrecK
<*> step readPrecV
<*> step readPrecR
<*> step readPrecR
)
showsMapPrec ::
(Int -> k -> ShowS) ->
(Int -> v -> ShowS) ->
(Int -> r -> ShowS) ->
Int ->
Map k v r ->
ShowS
showsMapPrec showsPrecK showsPrecV showsPrecR p =
let appPrec = 10
nextPrec = appPrec + 1
in \case
Tip -> showString "Tip"
Bin size k v l r ->
showParen (nextPrec <= p) $
showString "Bin "
. showsPrec nextPrec size
. showString " "
. showsPrecK nextPrec k
. showString " "
. showsPrecV nextPrec v
. showString " "
. showsPrecR nextPrec l
. showString " "
. showsPrecR nextPrec r
instance (Eq k, Eq v) => Eq1 (Map k v) where
liftEq = liftEq2 (==)
instance (Eq k) => Eq2 (Map k) where
liftEq2 = eqMap (==)
instance (Ord k, Ord v) => Ord1 (Map k v) where
liftCompare = liftCompare2 compare
instance (Ord k) => Ord2 (Map k) where
liftCompare2 = compareMap compare
-- | @since 0.1.2.0
instance (Read k, Read v) => Read1 (Map k v) where
liftReadPrec = liftReadPrec2 readPrec readListPrec
-- | @since 0.1.2.0
instance (Read k) => Read2 (Map k) where
liftReadPrec2 readPrecV _ readPrecR _ =
readMapPrec readPrec readPrecV readPrecR
instance (Show k, Show v) => Show1 (Map k v) where
liftShowsPrec = liftShowsPrec2 showsPrec showList
instance (Show k) => Show2 (Map k) where
liftShowsPrec2 showsPrecV _ showsPrecR _ =
showsMapPrec showsPrec showsPrecV showsPrecR