{-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE UndecidableInstances #-} module Pandora.Paradigm.Structure.Binary where import Pandora.Core.Functor (type (:.), type (:=)) import Pandora.Pattern.Category ((.), ($)) import Pandora.Pattern.Functor.Covariant (Covariant ((<$>), comap)) import Pandora.Pattern.Functor.Traversable (Traversable ((->>))) import Pandora.Pattern.Functor.Extractable (extract) import Pandora.Pattern.Functor.Avoidable (empty) import Pandora.Pattern.Transformer.Liftable (lift) import Pandora.Pattern.Object.Semigroup (Semigroup ((+))) import Pandora.Pattern.Object.Chain (Chain ((<=>))) import Pandora.Paradigm.Primary.Object.Boolean (Boolean (True, False)) import Pandora.Paradigm.Primary.Object.Ordering (order) import Pandora.Paradigm.Primary.Object.Numerator (Numerator (Numerator, Zero)) import Pandora.Paradigm.Primary.Object.Denumerator (Denumerator (One)) import Pandora.Paradigm.Primary.Functor.Function ((!), (%), (&)) import Pandora.Paradigm.Primary.Functor.Maybe (Maybe (Just, Nothing)) import Pandora.Paradigm.Primary.Functor.Predicate (Predicate (Predicate)) import Pandora.Paradigm.Primary.Functor.Product (Product ((:*:)), attached) import Pandora.Paradigm.Primary.Functor.Wye (Wye (End, Left, Right, Both)) import Pandora.Paradigm.Primary.Functor.Tagged (Tagged (Tag)) import Pandora.Paradigm.Primary.Transformer.Construction (Construction (Construct), deconstruct) import Pandora.Paradigm.Schemes (TU (TU), T_ (T_), T_U (T_U), type (<:.>), type (<:*:>)) import Pandora.Paradigm.Controlflow.Effect.Interpreted (run) import Pandora.Paradigm.Inventory.State (State, modify) import Pandora.Paradigm.Inventory.Store (Store (Store)) import Pandora.Paradigm.Inventory.Optics (type (:-.), (|>), (%~)) import Pandora.Paradigm.Structure.Ability.Nonempty (Nonempty) import Pandora.Paradigm.Structure.Ability.Nullable (Nullable (null)) import Pandora.Paradigm.Structure.Ability.Focusable (Focusable (Focusing, focusing), Location (Root)) import Pandora.Paradigm.Structure.Ability.Measurable (Measurable (Measural, measurement), Scale (Heighth), measure) import Pandora.Paradigm.Structure.Ability.Monotonic (Monotonic (resolve)) import Pandora.Paradigm.Structure.Ability.Insertable (Insertable (insert)) import Pandora.Paradigm.Structure.Ability.Rotatable (Rotatable (Rotational, rotation)) import Pandora.Paradigm.Structure.Ability.Substructure (Substructure (Substructural, substructure), sub) import Pandora.Paradigm.Structure.Ability.Zipper (Zipper) type Binary = Maybe <:.> Construction Wye rebalance :: Chain a => (Wye :. Construction Wye := a) -> Nonempty Binary a rebalance (Both x y) = extract x <=> extract y & order (Construct (extract y) $ Both x (rebalance $ deconstruct y)) (Construct (extract x) $ Both (rebalance $ deconstruct x) (rebalance $ deconstruct y)) (Construct (extract x) $ Both (rebalance $ deconstruct x) y) instance (forall a . Chain a) => Insertable Binary where insert x (run -> Nothing) = lift . Construct x $ End insert x tree@(run -> Just nonempty) = x <=> extract nonempty & order (sub @Left %~ insert x $ tree) tree (sub @Right %~ insert x $ tree) instance (forall a . Chain a) => Focusable Root Binary where type Focusing Root Binary a = Maybe a focusing (run . extract -> Nothing) = Store $ Nothing :*: Tag . TU . comap (Construct % End) focusing (run . extract -> Just x) = Store $ Just (extract x) :*: Tag . lift . resolve (Construct % deconstruct x) (rebalance $ deconstruct x) instance Measurable Heighth Binary where type Measural Heighth Binary a = Numerator measurement (run . extract -> Just bt) = Numerator $ measure @Heighth bt measurement (run . extract -> Nothing) = Zero instance Nullable Binary where null = Predicate $ \case { TU Nothing -> True ; _ -> False } instance Substructure Left Binary a where type Substructural Left Binary a = Binary a substructure empty_tree@(run . extract -> Nothing) = Store $ extract empty_tree :*: (!) empty_tree substructure (run . extract -> Just tree) = Tag . lift <$> (sub @Left |> can_be_empty) tree instance Substructure Right Binary a where type Substructural Right Binary a = Binary a substructure empty_tree@(run . extract -> Nothing) = Store $ extract empty_tree :*: (!) empty_tree substructure (run . extract -> Just tree) = Tag . lift <$> (sub @Right |> can_be_empty) tree can_be_empty :: Maybe (Construction Wye a) :-. Binary a can_be_empty maybe_tree = Store $ TU maybe_tree :*: run binary :: forall t a . (Traversable t, Chain a) => t a -> Binary a binary struct = attached $ run @(State (Binary a)) % empty $ struct ->> modify @(Binary a) . insert' where insert' :: a -> Binary a -> Binary a insert' x (run -> Nothing) = lift . Construct x $ End insert' x tree@(run -> Just nonempty) = x <=> extract nonempty & order (sub @Left %~ insert' x $ tree) tree (sub @Right %~ insert' x $ tree) type instance Nonempty Binary = Construction Wye instance Focusable Root (Construction Wye) where type Focusing Root (Construction Wye) a = a focusing (extract -> Construct x xs) = Store $ x :*: Tag . Construct % xs instance (forall a . Chain a) => Insertable (Construction Wye) where insert x nonempty = let change = Just . resolve (insert x) (Construct x End) in x <=> extract nonempty & order (sub @Left %~ change $ nonempty) nonempty (sub @Right %~ change $ nonempty) instance Measurable Heighth (Construction Wye) where type Measural Heighth (Construction Wye) a = Denumerator measurement (deconstruct . extract -> End) = One measurement (deconstruct . extract -> Left lst) = One + measure @Heighth lst measurement (deconstruct . extract -> Right rst) = One + measure @Heighth rst measurement (deconstruct . extract -> Both lst rst) = One + let (lm :*: rm) = measure @Heighth lst :*: measure @Heighth rst in lm <=> rm & order rm lm lm instance Substructure Left (Construction Wye) a where type Substructural Left (Construction Wye) a = Maybe :. Construction Wye := a substructure empty_tree@(extract -> Construct _ End) = Store $ Nothing :*: (empty_tree !) substructure (extract -> Construct x (Left lst)) = Store $ Just lst :*: Tag . Construct x . resolve Left End substructure (extract -> Construct x (Right rst)) = Store $ Nothing :*: Tag . Construct x . resolve (Both % rst) (Right rst) substructure (extract -> Construct x (Both lst rst)) = Store $ Just lst :*: Tag . Construct x . resolve (Both % rst) (Right rst) instance Substructure Right (Construction Wye) a where type Substructural Right (Construction Wye) a = Maybe :. Construction Wye := a substructure emtpy_tree@(extract -> Construct _ End) = Store $ Nothing :*: (emtpy_tree !) substructure (extract -> Construct x (Left lst)) = Store $ Nothing :*: Tag . Construct x . resolve (Both lst) (Left lst) substructure (extract -> Construct x (Right rst)) = Store $ Just rst :*: Tag . Construct x . resolve Right End substructure (extract -> Construct x (Both lst rst)) = Store $ Just rst :*: Tag . Construct x . resolve (Both lst) (Left lst) data Biforked a = Top | Leftward a | Rightward a type instance Zipper (Construction Wye) = Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye)) data Vertical a = Up a | Down a instance Rotatable Up (Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye))) where type Rotational Up (Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye))) a = Maybe :. (Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye))) := a rotation (run . extract -> focused :*: TU (TU (Leftward (Construct (T_ (parent :*: TU (Just rst))) next)))) = Just . T_U $ Construct parent (Both focused rst) :*: TU (TU next) rotation (run . extract -> focused :*: TU (TU (Leftward (Construct (T_ (parent :*: TU Nothing)) next)))) = Just . T_U $ Construct parent (Left focused) :*: TU (TU next) rotation (run . extract -> focused :*: TU (TU (Rightward (Construct (T_ (parent :*: TU (Just lst))) next)))) = Just . T_U $ Construct parent (Both lst focused) :*: TU (TU next) rotation (run . extract -> focused :*: TU (TU (Rightward (Construct (T_ (parent :*: TU Nothing)) next)))) = Just . T_U $ Construct parent (Right focused) :*: TU (TU next) rotation (extract -> T_U (_ :*: TU (TU Top))) = Nothing instance Rotatable (Down Left) (Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye))) where type Rotational (Down Left) (Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye))) a = Maybe :. (Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye))) := a rotation (run . extract -> Construct x (Left lst) :*: TU (TU next)) = Just . T_U . (:*:) lst . TU . TU . Leftward . Construct (T_ $ x :*: TU Nothing) $ next rotation (run . extract -> Construct x (Both lst rst) :*: TU (TU next)) = Just . T_U . (:*:) lst . TU . TU . Leftward . Construct (T_ $ x :*: TU (Just rst)) $ next rotation (run . extract -> Construct _ (Right _) :*: _) = Nothing rotation (run . extract -> Construct _ End :*: _) = Nothing instance Rotatable (Down Right) (Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye))) where type Rotational (Down Right) (Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye))) a = Maybe :. (Construction Wye <:*:> ((Biforked <:.> Construction Biforked) <:.> T_ Covariant (Maybe <:.> Construction Wye))) := a rotation (run . extract -> Construct x (Right rst) :*: TU (TU next)) = Just . T_U . (:*:) rst . TU . TU . Rightward . Construct (T_ $ x :*: TU Nothing) $ next rotation (run . extract -> Construct x (Both lst rst) :*: TU (TU next)) = Just . T_U . (:*:) rst . TU . TU . Rightward . Construct (T_ $ x :*: TU (Just lst)) $ next rotation (run . extract -> Construct _ (Left _) :*: _) = Nothing rotation (run . extract -> Construct _ End :*: _) = Nothing