packages feed

pandora-0.5.6: Pandora/Paradigm/Structure/Some/Rose.hs

{-# OPTIONS_GHC -fno-warn-orphans #-}
module Pandora.Paradigm.Structure.Some.Rose where

import Pandora.Core.Functor (type (:.), type (>), type (<<), type (>>>))
import Pandora.Core.Interpreted (run, unite, (<~))
import Pandora.Pattern.Semigroupoid ((.))
import Pandora.Pattern.Category ((<--), (<---), (<----), (<-----), (<------), (<-------))
import Pandora.Pattern.Kernel (constant)
import Pandora.Pattern.Functor.Covariant (Covariant ((<-|-), (<-|----)))
import Pandora.Pattern.Functor.Contravariant ((>-|-))
import Pandora.Pattern.Functor.Traversable ((<-/-))
import Pandora.Pattern.Functor.Bindable (Bindable ((=<<), (====<<), (=====<<), (======<<)))
import Pandora.Pattern.Transformation.Liftable (lift)
import Pandora.Pattern.Transformation.Lowerable (lower)
import Pandora.Pattern.Object.Setoid (Setoid ((?=)))
import Pandora.Pattern.Object.Semigroup ((+))
import Pandora.Pattern.Operation.Exponential ((%), (.:..))
import Pandora.Pattern.Operation.Product ((:*:) ((:*:)), attached)
import Pandora.Paradigm.Algebraic (type (<:*:>), (<:*:>))
import Pandora.Paradigm.Algebraic.Functor ((<-*-), (<-*----), extract, point, empty, void)
import Pandora.Paradigm.Primary.Auxiliary (Vertical (Up, Down), Horizontal (Left, Right))
import Pandora.Paradigm.Primary.Functor.Exactly (Exactly (Exactly))
import Pandora.Paradigm.Primary.Functor.Maybe (Maybe (Just, Nothing))
import Pandora.Paradigm.Primary.Functor.Predicate (equate)
import Pandora.Paradigm.Primary.Functor.Tagged (Tagged)
import Pandora.Paradigm.Primary.Transformer.Construction (Construction (Construct), deconstruct)
import Pandora.Paradigm.Primary.Transformer.Reverse (Reverse (Reverse))
import Pandora.Paradigm.Schemes (TU (TU), TT (TT), T_U (T_U), P_Q_T (P_Q_T),  type (<::>), type (<:.>))
import Pandora.Paradigm.Controlflow.Effect.Transformer ((:>), wrap)
import Pandora.Paradigm.Inventory.Some.State (State, change, current)
import Pandora.Paradigm.Inventory.Some.Store (Store (Store))
import Pandora.Paradigm.Inventory.Some.Optics (Lens, view, mutate, replace, primary)
import Pandora.Paradigm.Inventory (zoom, overlook, probably)
import Pandora.Paradigm.Structure.Ability.Morphable (Morphable (Morphing, morphing), Morph (Lookup, Element, Key), premorph, find)
import Pandora.Paradigm.Structure.Modification.Nonempty (Nonempty)
import Pandora.Paradigm.Structure.Ability.Slidable (Slidable (Sliding, slide))
import Pandora.Paradigm.Structure.Ability.Substructure (Substructure (Substance, substructure)
	, Segment (Rest, Ancestors, Siblings, Children, Tree, Forest), Location (Focused), sub)
import Pandora.Paradigm.Structure.Interface.Zipper (Zipper, Zippable (Breadcrumbs, fasten, unfasten))
import Pandora.Paradigm.Structure.Interface.Stack (Stack (pop, push, top))
import Pandora.Paradigm.Structure.Modification.Prefixed (Prefixed)
import Pandora.Paradigm.Structure.Modification.Tape (Tape)
import Pandora.Paradigm.Structure.Some.List (List)

type Rose = Maybe <::> Construction List

--------------------------------------- Prefixed rose tree -----------------------------------------

instance Setoid k => Morphable (Lookup Key) (Prefixed Rose k) where
	type Morphing (Lookup Key) (Prefixed Rose k) = (->) (Nonempty List k) <:.> Maybe
	morphing prefixed_rose_tree = case run <-- premorph prefixed_rose_tree of
		TT Nothing -> TU <-- constant Nothing
		TT (Just tree) -> TU <-- find_rose_sub_tree % tree

-- TODO: Ineffiecient - we iterate over all branches in subtree, but we need to short-circuit on the first matching part of
--instance Setoid k => Morphable (Vary Element) (Prefixed Rose k) where
--	type Morphing (Vary Element) (Prefixed Rose k) = ((:*:) (Nonempty List k) <:.> Exactly) <:.:> Prefixed Rose k > (->)
--	morphing (run . run . premorph -> Nothing) = T_U ! \(TU (Construct key _ :*: Exactly value)) -> Prefixed . lift ! Construct (key :*: value) empty
--	morphing (run . run . premorph -> Just (Construct focused subtree)) = T_U ! \(TU (breadcrumbs :*: Exactly value)) -> case breadcrumbs of
--		Construct key Nothing -> Prefixed . lift ! attached focused == key ? Construct (key :*: value) subtree ! Construct focused subtree
--		Construct key (Just keys) -> Prefixed . lift ! attached focused != key ? Construct focused subtree
--			! Construct focused ! vary @Element @_ @_ @(Nonempty (Prefixed Rose k)) keys value -#=!> subtree

---------------------------------- Non-empty prefixed rose tree ------------------------------------

-- TODO: Ineffiecient - we iterate over all branches in subtree, but we need to short-circuit on the first matching part of
--instance Setoid k => Morphable (Vary Element) (Prefixed (Construction List) k) where
--	type Morphing (Vary Element) (Prefixed (Construction List) k) =
--		((:*:) (Nonempty List k) <:.> Exactly) <:.:> Prefixed (Construction List) k > (->)
--	morphing (run . premorph -> Construct x (TU Nothing)) = T_U ! \(TU (breadcrumbs :*: Exactly value)) -> case breadcrumbs of
--		Construct key Nothing -> Prefixed ! attached x == key ? Construct (key :*: value) empty ! Construct x empty
--		Construct _ (Just _) -> Prefixed ! Construct x (TU Nothing)
--	morphing (run . premorph -> Construct x (TU (Just subtree))) = T_U ! \(TU (breadcrumbs :*: Exactly value)) -> case breadcrumbs of
--		Construct key Nothing -> Prefixed ! attached x != key ? Construct x # lift subtree
--			! Construct (key :*: value) (lift subtree)
--		Construct key (Just keys) -> Prefixed ! attached x != key ? Construct x # lift subtree
--			! Construct (key :*: value) . lift ! vary @Element @_ @_ @(Nonempty (Prefixed Rose k)) keys value -#=!> subtree

find_rose_sub_tree :: forall k a . Setoid k => Nonempty List k -> Nonempty Rose >>> k :*: a -> Maybe a
find_rose_sub_tree (Construct k ks) tree = k ?= attached (extract tree)
	<----- case ks of
		Just keys -> find_rose_sub_tree keys =<< subtree keys
		Nothing -> Just <--- extract <-- extract tree
	<----- Nothing where

	subtree :: Nonempty List k -> Maybe :. Nonempty Rose >>> k :*: a
	subtree keys = find @Element
		<---- attached . extract
			>-|- equate <-- extract keys
		<---- deconstruct tree

------------------------------ Non-empty rose tree zipper -----------------------------

type Roses = List <::> Construction List

instance Zippable Rose where
	type Breadcrumbs Rose = Roses <:*:> List <::> Tape Roses
	fasten (TT (Just (Construct x xs))) = Just <----- Exactly x <:*:> TT xs <:*:> TT empty
	fasten (TT Nothing) = Nothing
	unfasten :: forall e . Zipper Rose e -> Nonempty Rose e
	unfasten (T_U (Exactly focus :*: T_U (TT children :*: TT ancestors))) =
		attached <-- (cover <-/- ancestors) <~ Construct focus children where

		cover :: Tape Roses e -> State << Nonempty Rose e << ()
		cover (T_U (Exactly x :*: T_U (Reverse (TT lf) :*: TT rf))) =

			void <--- change @(Nonempty Rose e) <-- \nrt ->
				Construct <------- x <------- lift <------ unfasten @List
					<----- Exactly nrt <:*:> Reverse lf <:*:> rf

-- TODO: Try to use substructure @Right . substructure @Right . substructure @Right . substructure @Right here
instance Substructure Ancestors (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	type Substance Ancestors (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = List <::> Tape Roses
	substructure = P_Q_T <-- \zipper -> case run @(->) <-|- run <-- lower zipper of
		Exactly x :*: down :*: up -> Store <--- up :*: lift . (Exactly x <:*:>) . (down <:*:>)

-- TODO: Try to use substructure @Left . substructure @Right here
instance Substructure Children (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	type Substance Children (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Roses
	substructure = P_Q_T <-- \zipper -> case run @(->) <-|- run <-- lower zipper of
		Exactly x :*: down :*: up -> Store <--- down :*: lift . (Exactly x <:*:>) . (<:*:> up)

-- Think about lens methods/operators that could make this code easier
instance Substructure Siblings (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	type Substance Siblings (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Maybe <::> (Reverse Roses <:*:> Roses)
	substructure = P_Q_T <-- \zipper -> case run @(->) <-|- run <-- lower zipper of
		Exactly x :*: down :*: up -> Store
			<--- (TT <---- view <-- sub @Rest <-|- view <-- top @List <-- run up)
				:*: \siblings -> lift <----- Exactly x <:*:> down
					<:*:> TT <--- mutate (replace <-|- run siblings <-*- Just <-- sub @Rest <-*-)
						<-- top @List <-- run up

instance Substructure (Focused Tree) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	type Substance (Focused Tree) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Construction List
	substructure = P_Q_T <-- \zipper -> case run @(->) <-|- run <-- lower zipper of
		Exactly x :*: children :*: up -> Store <--- Construct x (run children) :*: lift . T_U . ((<:*:> up) <-|-) . run . run

-- TODO: Refactor this instance, looks too complicated
-- TODO: it seem like this instance is wrong, when I try to update the focus, I lost andestors
instance Substructure (Focused Forest) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	type Substance (Focused Forest) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Tape List <::> Nonempty Rose
	substructure :: forall e . Lens (Tape List <::> Nonempty Rose)
		((Tagged (Focused Forest) <:.> (Exactly <:*:> Roses <:*:> List <::> Tape Roses)) > e) e
	substructure = P_Q_T <-- \zipper -> case run @(->) <-|- run @(->) <-- lower zipper of
		Exactly root :*: down :*: up -> Store <--- TT focused :*: lift . updated where

			focused :: Tape List > Nonempty Rose e
			focused = case run <--- view <-- top @List <-- run up of
				Nothing -> Exactly tree <:*:> Reverse empty <:*:> empty
				Just (T_U (Exactly _ :*: T_U (Reverse left :*: right)))
					-> Exactly tree <:*:> Reverse (run left) <:*:> run right

			tree :: Nonempty Rose e
			tree = Construct root <-- run down

			updated :: (Tape List <::> Nonempty Rose) e -> (Exactly <:*:> Roses <:*:> List <::> Tape Roses) e
			updated (TT (T_U (Exactly (Construct new_root new_down) :*: T_U (Reverse left_ :*: right_)))) =
				Exactly new_root <:*:> unite new_down <:*:> TT
					<--- mutate <-- (update_sides (Reverse (TT left_) <:*:> TT right_) <-|-) <-- top @List <-- run up

			update_sides :: (Reverse Roses <:*:> Roses) e -> Tape Roses e -> Tape Roses e
			update_sides sides tape = replace <-- sides <-- sub @Rest <-- tape

-- TODO: Try to use substructure @Left . substructure @Right . substructure @Right here
-- instance Substructure (Left Siblings) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
-- 	type Substance (Left Siblings) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Reverse Roses
-- 	substructure = P_Q_T <-- \zipper -> case run @(->) <-|- run <-- lower zipper of
-- 		Exactly x :*: down :*: up -> Store
-- 			<--- (view (sub @Left) . view (sub @Rest) <-- up)
-- 				:*: \left' -> lift (Exactly x <:*:> down <:*:> mutate (mutate (constant left') (sub @Left)) (sub @Rest) up)

-- TODO: Try to use substructure  @Left . substructure @Right . substructure @Right . substructure @Right here
-- instance Substructure (Right Siblings) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
-- 	type Substance (Right Siblings) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Roses
	--substructure = P_Q_T <-- \zipper -> case run @(->) <-|-|-|- run @(->) <-|-|- run @(->) <-|- run <-- lower zipper of
	--	Exactly x :*: down :*: left :*: right :*: rest -> Store <--- right :*: lift . (Exactly x <:*:>) . (down <:*:>) . (left <:*:>) . (<:*:> rest)

--instance Morphable (Into (Exactly <:*:> Roses <:*:> List <::> Tape Roses)) (Construction List) where
	--type Morphing (Into (Exactly <:*:> Roses <:*:> List <::> Tape Roses)) (Construction List) = Exactly <:*:> Roses <:*:> List <::> Tape Roses
	--morphing nonempty_rose_tree = case premorph nonempty_rose_tree of
		--Construct x xs -> Exactly x <:*:> unite xs <:*:> empty <:*:> empty <:*:> empty

--instance Morphable (Rotate Up) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	--type Morphing (Rotate Up) (Exactly <:*:> Roses <:*:> List <::> Tape Roses) =
		--Maybe <::> (Exactly <:*:> Roses <:*:> List <::> Tape Roses)
	--morphing (premorph -> z) = TT <----- restruct <-|-- identity @(->) <-/- pop @List <~ run (view <-- sub @Ancestors <-- z) where
--
		---- TODO: Add type declaration
		--restruct (parents :*: parent) =
			--let child_node = extract <--- view <-- sub @Root <-- z in
			--let central_children = run <--- view <-- sub @Children <-- z in
			----let left_children = run @(->) <---- run <--- view <-- sub @(Left Siblings) <-- z in
			--let right_children = run <--- view <-- sub @(Right Siblings) <-- z in
			--view <-- sub @Root <-- parent
				-- <:*:> unite <-- left_children + point (Construct child_node central_children) + right_children
				-- <:*:> view <--- sub @(Left Branch) <--- view <-- sub @Rest <-- parent
				-- <:*:> view <--- sub @(Right Branch) <--- view <-- sub @Rest <-- parent
				-- <:*:> unite parents

instance Slidable Up (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	type Sliding Up (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Maybe
	slide :: forall e . State > Zipper Rose e :> Maybe >>> ()
	slide = void . wrap . zoom @(Zipper Rose e) (sub @(Focused Tree)) . change . constant ======<< merging
		<-|---- wrap <--- zoom @(Zipper Rose e) <-- sub @(Focused Tree) <-- current
		<-*---- lift . extract ====<< wrap .:.. zoom @(Zipper Rose e) <--- sub @Ancestors
			<--- zoom <-- primary <-- overlook (pop @List) where

		merging :: Nonempty Rose e -> Tape (List <::> Nonempty Rose) e -> Nonempty Rose e
		merging x (T_U (Exactly p :*: T_U (Reverse ls :*: rs))) =
			-- TODO: This is wrong, we should add left part in reverse order
			Construct p <-- run ls + point x + run rs

instance Slidable Left (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	type Sliding Left (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Maybe
	slide :: forall e . State > Zipper Rose e :> Maybe >>> ()
	slide = void <------- lift . extract
		=====<< wrap .:.. zoom @(Zipper Rose e)
			<----- sub @(Focused Forest)
			<----- zoom <---- primary <---- overlook
				<--- probably <-- slide @Left

instance Slidable Right (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	type Sliding Right (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Maybe
	slide :: forall e . State > Zipper Rose e :> Maybe >>> ()
	slide = void <------- lift . extract
		=====<< wrap .:.. zoom @(Zipper Rose e)
			<----- sub @(Focused Forest)
			<----- zoom <---- primary <---- overlook
				<--- probably <-- slide @Right

instance Slidable Down (Exactly <:*:> Roses <:*:> List <::> Tape Roses) where
	type Sliding Down (Exactly <:*:> Roses <:*:> List <::> Tape Roses) = Maybe
	slide :: forall e . State > Zipper Rose e :> Maybe >>> ()
	slide = void . wrap . zoom @(Zipper Rose e) (sub @Ancestors) . zoom primary . overlook . push @List . ancestor
		====<< wrap . zoom @(Zipper Rose e) (sub @(Focused Tree)) . change . constant
		====<< lift . extract ====<< wrap .:.. zoom @(Zipper Rose e) <---- sub @(Focused Tree)
			<---- zoom <--- sub @Rest <--- zoom <-- primary <-- overlook (pop @List) where

		ancestor :: Construction List e -> Tape Roses e
		ancestor (Construct x xs) = Exactly x <:*:> Reverse <-- unite empty <:*:> unite xs