{-# OPTIONS_GHC -fno-warn-orphans #-} module Pandora.Paradigm.Structure.Rose where import Pandora.Core.Functor (type (:.), type (:=)) import Pandora.Pattern.Category ((.), ($)) import Pandora.Pattern.Functor.Covariant (Covariant (comap)) import Pandora.Pattern.Functor.Extractable (extract) import Pandora.Pattern.Functor.Avoidable (Avoidable (empty)) import Pandora.Pattern.Transformer.Liftable (lift) import Pandora.Paradigm.Primary.Object.Boolean (Boolean (True, False)) 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 ((:*:))) import Pandora.Paradigm.Primary.Functor.Tagged (Tagged (Tag)) import Pandora.Paradigm.Primary.Transformer.Construction (Construction (Construct), deconstruct) import Pandora.Paradigm.Schemes.TU (TU (TU), type (<:.>)) import Pandora.Paradigm.Controlflow.Effect.Interpreted (run) import Pandora.Paradigm.Inventory.Store (Store (Store)) import Pandora.Paradigm.Structure.Ability.Focusable (Focusable (Focusing, focusing), Location (Root)) import Pandora.Paradigm.Structure.Ability.Monotonic (resolve) import Pandora.Paradigm.Structure.Ability.Nonempty (Nonempty) import Pandora.Paradigm.Structure.Ability.Nullable (Nullable (null)) import Pandora.Paradigm.Structure.Ability.Substructure (Substructure (Substructural, substructure)) import Pandora.Paradigm.Structure.Stack (Stack) type Rose = Maybe <:.> Construction Stack instance Focusable Root Rose where type Focusing Root Rose a = Maybe a focusing (run . extract -> Nothing) = Store $ Nothing :*: Tag . TU . comap (Construct % empty) focusing (run . extract -> Just rose) = Store $ Just (extract rose) :*: Tag . resolve (lift . Construct % deconstruct rose) (TU Nothing) instance Nullable Rose where null = Predicate $ \case { TU Nothing -> True ; _ -> False } instance Substructure Just Rose a where type Substructural Just Rose a = Stack :. Construction Stack := a substructure (run . extract -> Nothing) = Store $ TU Nothing :*: (Tag (TU Nothing) !) substructure (run . extract -> Just (Construct x xs)) = Store $ xs :*: Tag . lift . Construct x type instance Nonempty Rose = Construction Stack instance Focusable Root (Construction Stack) where type Focusing Root (Construction Stack) a = a focusing (Tag rose) = Store $ extract rose :*: Tag . Construct % deconstruct rose instance Substructure Just (Construction Stack) a where type Substructural Just (Construction Stack) a = Stack :. Construction Stack := a substructure (extract -> Construct x xs) = Store $ xs :*: Tag . Construct x