yaya-containers-0.1.2.0: src/Yaya/Containers/Pattern/Set.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE Safe #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Yaya.Containers.Pattern.Set
( SetF (BinF, TipF),
)
where
import "base" Control.Applicative
( Alternative ((<|>)),
Applicative ((<*>)),
(*>),
)
import "base" Control.Category (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 (fmap), (<$), (<$>))
import "base" Data.Ord (Ord (compare, (<=)), Ordering (EQ, GT, LT))
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 (Read (readListPrec, readPrec), expectP, parens)
import "base" Text.ParserCombinators.ReadPrec (prec, step)
import qualified "base" Text.Read.Lex as Lex
import qualified "containers" Data.Set.Internal as Set
import "yaya" Yaya.Fold
( Projectable (project),
Recursive (cata),
Steppable (embed),
)
import "base" Prelude (Num ((+)))
#if MIN_VERSION_base(4, 18, 0)
import "base" Data.Functor.Classes
( Eq1,
Eq2 (liftEq2),
Ord1,
Ord2 (liftCompare2),
Read1 (liftReadPrec),
Read2 (liftReadPrec2),
Show1,
Show2 (liftShowsPrec2),
)
import "base" Text.Show (Show (showsPrec), showParen, showString)
#else
import "base" Data.Functor.Classes
( Eq1 (liftEq),
Eq2 (liftEq2),
Ord1 (liftCompare),
Ord2 (liftCompare2),
Read1 (liftReadPrec),
Read2 (liftReadPrec2),
Show1 (liftShowsPrec),
Show2 (liftShowsPrec2),
)
import "base" Text.Show (Show (showList, showsPrec), showParen, showString)
#endif
data SetF a r = TipF | BinF Set.Size a r r
deriving stock
( Eq,
Ord,
Generic,
-- | @since 0.1.2.0
Read,
Show,
Foldable,
Functor,
Generic1,
Traversable
)
instance Projectable (->) (Set.Set a) (SetF a) where
project Set.Tip = TipF
project (Set.Bin size a l r) = BinF size a l r
instance Recursive (->) (Set.Set a) (SetF a) where
cata φ = φ . fmap (cata φ) . project
instance Steppable (->) (Set.Set a) (SetF a) where
embed TipF = Set.Tip
embed (BinF size a l r) = Set.Bin size a l r
#if MIN_VERSION_base(4, 18, 0)
instance (Eq a) => Eq1 (SetF a)
#else
instance (Eq a) => Eq1 (SetF a) where
liftEq = liftEq2 (==)
#endif
instance Eq2 SetF where
liftEq2 f g = Tuple.curry $ \case
(TipF, TipF) -> True
(BinF size a l r, BinF size' a' l' r') ->
size == size' && f a a' && g l l' && g r r'
(_, _) -> False
#if MIN_VERSION_base(4, 18, 0)
instance (Ord a) => Ord1 (SetF a)
#else
instance (Ord a) => Ord1 (SetF a) where
liftCompare = liftCompare2 compare
#endif
instance Ord2 SetF where
liftCompare2 f g = Tuple.curry $ \case
(TipF, TipF) -> EQ
(TipF, BinF {}) -> LT
(BinF {}, TipF) -> GT
(BinF size a l r, BinF size' a' l' r') ->
compare size size' <> f a a' <> g l l' <> g r r'
-- | @since 0.1.2.0
instance (Read a) => Read1 (SetF a) where
liftReadPrec = liftReadPrec2 readPrec readListPrec
-- | @since 0.1.2.0
instance Read2 SetF where
liftReadPrec2 readPrecA _ readPrecR _ =
let appPrec = 10
in parens . prec appPrec $
TipF
<$ expectP (Lex.Ident "TipF")
<|> expectP (Lex.Ident "BinF")
*> ( BinF
<$> step readPrec
<*> step readPrecA
<*> step readPrecR
<*> step readPrecR
)
#if MIN_VERSION_base(4, 18, 0)
instance (Show a) => Show1 (SetF a)
#else
instance (Show a) => Show1 (SetF a) where
liftShowsPrec = liftShowsPrec2 showsPrec showList
#endif
instance Show2 SetF where
liftShowsPrec2 showsPrecA _ showsPrecR _ p =
let appPrec = 10
nextPrec = appPrec + 1
in \case
TipF -> showString "TipF"
BinF size a l r ->
showParen (nextPrec <= p) $
showString "BinF "
. showsPrec nextPrec size
. showString " "
. showsPrecA nextPrec a
. showString " "
. showsPrecR nextPrec l
. showString " "
. showsPrecR nextPrec r