packages feed

pandora-0.5.2: Pandora/Paradigm/Structure/Some/List.hs

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

import Pandora.Core.Functor (type (:.), type (<), type (>))
import Pandora.Core.Impliable (imply)
import Pandora.Pattern.Semigroupoid ((.))
import Pandora.Pattern.Category ((<--), (<---), (<----), (<-----), (-->), (--->), (---->), identity)
import Pandora.Pattern.Kernel (constant)
import Pandora.Pattern.Functor.Covariant (Covariant, Covariant ((<-|-), (<-|--), (<-|-|-)))
import Pandora.Pattern.Functor.Traversable (Traversable ((<<-), (<<--)))
import Pandora.Pattern.Functor.Extendable (Extendable ((<<=)))
import Pandora.Pattern.Functor.Bindable (Bindable ((=<<), (==<<), (===<<), (====<<)))
import Pandora.Pattern.Functor.Adjoint (Adjoint ((|-)))
import Pandora.Pattern.Transformer.Liftable (lift)
import Pandora.Pattern.Transformer.Lowerable (lower)
import Pandora.Pattern.Object.Setoid (Setoid ((==), (?==)))
import Pandora.Pattern.Object.Semigroup (Semigroup ((+)))
import Pandora.Pattern.Object.Monoid (Monoid (zero))
import Pandora.Paradigm.Primary.Algebraic ((<-*-), (<-*--), (.-*-), (.-+-), (.:..), extract, point, empty, void)
import Pandora.Paradigm.Primary.Algebraic.Product ((:*:) ((:*:)), attached)
import Pandora.Paradigm.Primary.Algebraic.Exponential ((%))
import Pandora.Paradigm.Primary.Algebraic ((<-|-<-|-))
import Pandora.Paradigm.Primary.Object.Boolean (Boolean (True))
import Pandora.Paradigm.Primary.Functor.Maybe (Maybe (Just, Nothing))
import Pandora.Paradigm.Primary.Functor.Exactly (Exactly (Exactly))
import Pandora.Paradigm.Primary.Functor.Predicate (Predicate (Predicate))
import Pandora.Paradigm.Primary.Functor.Tagged (Tagged (Tag))
import Pandora.Paradigm.Primary.Functor.Wye (Wye (Left, Right))
import Pandora.Paradigm.Primary.Transformer.Construction (Construction (Construct), deconstruct, (.-+))
import Pandora.Paradigm.Primary.Transformer.Reverse (Reverse (Reverse))
import Pandora.Paradigm.Primary (twosome)
import Pandora.Paradigm.Inventory.Ability.Gettable (get)
import Pandora.Paradigm.Inventory.Ability.Settable (set)
import Pandora.Paradigm.Inventory.Ability.Modifiable (modify)
import Pandora.Paradigm.Inventory.Some.State (State, fold)
import Pandora.Paradigm.Inventory.Some.Store (Store (Store))
import Pandora.Paradigm.Inventory.Some.Optics (Convex, Obscure, Lens)
import Pandora.Paradigm.Controlflow.Effect.Interpreted (run, (<~), (=#-))
import Pandora.Paradigm.Schemes.TT (TT (TT), type (<::>))
import Pandora.Paradigm.Schemes.TU (TU (TU))
import Pandora.Paradigm.Schemes.T_U (T_U (T_U), type (<:.:>))
import Pandora.Paradigm.Schemes.P_Q_T (P_Q_T (P_Q_T))
import Pandora.Paradigm.Structure.Ability.Nonempty (Nonempty)
import Pandora.Paradigm.Structure.Ability.Zipper (Zippable (Breadcrumbs), Zipper, Tape)
import Pandora.Paradigm.Structure.Ability.Monotonic (resolve)
import Pandora.Paradigm.Structure.Ability.Morphable (Morphable (Morphing, morphing)
	, Morph (Rotate, Into, Push, Pop, Delete, Find, Lookup, Element, Key)
	, Occurrence (All, First), premorph, rotate, item, filter, find, lookup, into)
import Pandora.Paradigm.Structure.Ability.Substructure (Substructure (Substance, substructure, sub), Segment (Root, Tail))
import Pandora.Paradigm.Structure.Interface.Stack (Stack (Popping, Pushing, Topping, push, pop, top))
import Pandora.Paradigm.Structure.Modification.Combinative (Combinative)
import Pandora.Paradigm.Structure.Modification.Comprehension (Comprehension (Comprehension))
import Pandora.Paradigm.Structure.Modification.Prefixed (Prefixed (Prefixed))
import Pandora.Paradigm.Structure.Modification.Turnover (Turnover (Turnover))

-- | Linear data structure that serves as a collection of elements
type List = Maybe <::> Construction Maybe

instance Setoid a => Setoid (List a) where
	TT ls == TT rs = ls == rs

instance Semigroup (List a) where
	TT Nothing + TT ys = TT ys
	TT (Just (Construct x xs)) + TT ys = lift . Construct x . run
		<-- TT @Covariant @Covariant xs + TT @Covariant @Covariant ys

instance Monoid (List a) where
	zero = empty

instance Morphable Push List where
	type Morphing Push List = Exactly <:.:> List > (->)
	morphing (premorph -> xs) = T_U <-- lift . (Construct % run xs) . extract

instance Morphable Pop List where
	type Morphing Pop List = List
	morphing (premorph -> xs) = resolve deconstruct Nothing =#- xs

instance Morphable (Find Element) List where
	type Morphing (Find Element) List = Predicate <:.:> Maybe > (->)
	morphing list = case run --> premorph list of
		Nothing -> T_U <-- \_ -> Nothing
		Just (Construct x xs) -> T_U <-- \p ->
			p <~ x ?== True <----- Just x
				<----- find @Element @List @Maybe <-- p <-- TT xs

instance Morphable (Delete First) List where
	type Morphing (Delete First) List = Predicate <:.:> List > (->)
	morphing list = case run --> premorph list of
		Nothing -> T_U <-- constant empty
		Just (Construct x xs) -> T_U <-- \p -> 
			p <~ x ?== True <----- TT xs
				<----- lift . Construct x . run . filter @First @List p <-- TT xs

instance Morphable (Delete All) List where
	type Morphing (Delete All) List = Predicate <:.:> List > (->)
	morphing list = case run <--- premorph list of
		Nothing -> T_U <-- constant empty
		Just (Construct x xs) -> T_U <-- \p -> p <~ x ?== True
				<----- filter @All @List p <-- TT xs
				<----- lift . Construct x . run . filter @All @List p <-- TT xs

instance Stack List where
	type Topping List = Maybe
	type Popping List = List
	type Pushing List = List
	top = P_Q_T <-- \list -> case list of
		TT Nothing -> Store <--- Nothing :*: constant empty
		TT (Just xs) -> Store <--- Just (extract xs) :*: \new -> case new of
			Nothing -> TT <-- deconstruct xs
			Just x -> TT <--- Construct x . Just <-|- deconstruct xs
	pop = resolve @(Nonempty List _) (\(Construct x xs) -> constant (Just x) <-|- set @State (TT xs)) (point Nothing) . run ==<< get @State
	push x = point x .-*- modify @State (item @Push x)

instance Substructure Root List where
	type Substance Root List = Maybe
	substructure = P_Q_T <-- \zipper -> case run --> lower zipper of
		Just (Construct x xs) -> Store <--- Just x :*: lift . resolve (lift . (Construct % xs)) zero
		Nothing -> Store <--- Nothing :*: lift . resolve (lift . point) zero

instance Substructure Tail List where
	type Substance Tail List = List
	substructure = P_Q_T <-- \source -> case run . lower <-- source of
		Just ns -> lift . lift @(->) <-|- run (sub @Tail) ns
		Nothing -> Store <--- zero :*: lift . identity

-- | Transform any traversable structure into a list
linearize :: forall t a . Traversable (->) (->) t => t a -> List a
linearize = TT . extract . (run @(->) @(State (Maybe :. Nonempty List > a)) % Nothing) . fold (Just .:.. Construct)

----------------------------------------- Non-empty list -------------------------------------------

type instance Nonempty List = Construction Maybe

instance {-# OVERLAPS #-} Semigroup (Construction Maybe a) where
	Construct x Nothing + ys = Construct x <-- Just ys
	Construct x (Just xs) + ys = Construct x . Just <-- xs + ys

instance Morphable (Find Element) (Construction Maybe) where
	type Morphing (Find Element) (Construction Maybe) = Predicate <:.:> Maybe > (->)
	morphing (premorph -> Construct x xs) = T_U <-- \p -> p <~ x ?== True <----- Just x
		<----- find @Element @(Nonempty List) @Maybe <-- p ===<< xs

instance Morphable (Into List) (Construction Maybe) where
	type Morphing (Into List) (Construction Maybe) = List
	morphing = lift . premorph

instance Morphable (Into List) (Construction Maybe <::> Maybe) where
	type Morphing (Into List) (Construction Maybe <::> Maybe) = List
	morphing nonempty_list_with_maybe_elements = case run . premorph ---> nonempty_list_with_maybe_elements of
		Construct (Just x) (Just xs) -> item @Push x --> into @List --> TT @Covariant @Covariant xs
		Construct (Just x) Nothing -> point x
		Construct Nothing (Just xs) -> into @List --> TT @Covariant @Covariant xs
		Construct Nothing Nothing -> empty

instance Morphable Push (Construction Maybe) where
	type Morphing Push (Construction Maybe) = Exactly <:.:> Construction Maybe > (->)
	morphing (premorph -> xs) = T_U <-- \(Exactly x) -> Construct x <-- Just xs

instance Substructure Root (Construction Maybe) where
	type Substance Root (Construction Maybe) = Exactly
	substructure = P_Q_T <-- \source -> case lower source of
		Construct x xs -> Store <--- Exactly x :*: lift . (Construct % xs) . extract

instance Substructure Tail (Construction Maybe) where
	type Substance Tail (Construction Maybe) = List
	substructure = P_Q_T <-- \source -> case lower source of
		Construct x xs -> Store <--- TT xs :*: lift . Construct x . run

instance Stack (Construction Maybe) where
	type Topping (Construction Maybe) = Exactly
	type Popping (Construction Maybe) = Construction Maybe
	type Pushing (Construction Maybe) = Construction Maybe
	top = P_Q_T <-- \xs -> Store <--- Exactly (extract xs) :*: \(Exactly new) -> Construct new <--- deconstruct xs
	-- It will never return you the last element
	pop = (\(Construct x xs) -> constant x <-|-|- set @State <<- xs) =<< get @State
	push x = point x .-*- (modify @State <-- Construct x . Just)

---------------------------------------- Combinative list ------------------------------------------

type instance Combinative List = Comprehension Maybe

----------------------------------------- Zipper of list -------------------------------------------

instance Zippable List where
	type Breadcrumbs List = Reverse List <:.:> List > (:*:)

instance {-# OVERLAPS #-} Traversable (->) (->) (Tape List) where
	f <<- TU (Tag (T_U (Exactly x :*: T_U (left :*: right)))) = 
		(\past' x' left' -> lift <---- twosome <-- Exactly x' <--- twosome <-- left' <-- run past')
			<-|- f <<- Reverse right <-*- f x <-*- f <<- left

-- instance {-# OVERLAPS #-} Extendable (->) (Tape List) where
	-- f <<= z = let move rtt = TT . deconstruct <----- run . rtt .-+ z in
		-- imply @(Tape List _)
			-- <---- f z
			-- <---- f <-|-- move <-- rotate @Left
			-- <---- f <-|-- move <-- rotate @Right

instance Morphable (Rotate Left) (Turnover < Tape List) where
	type Morphing (Rotate Left) (Turnover < Tape List) = Turnover < Tape List
	morphing s@(lower . run . premorph -> T_U (Exactly x :*: T_U (Reverse left :*: right))) =
		resolve @(Tape List _) <--- Turnover <--- premorph s <----
			(rotate_over x <-|- run right) .-+- (rotate_left x right <-|- run left) where

		rotate_left :: a -> List a -> Nonempty List a -> Tape List a
		rotate_left focused rs (Construct lx lxs) = imply @(Tape List _) <-- lx <-- TT lxs <-- item @Push focused rs

		rotate_over :: a -> Nonempty List a -> Tape List a
		rotate_over focused rs = let new_left = attached <--- run <-- put_over <<- rs <-- point focused in
			imply @(Tape List _) <--- extract new_left <--- TT <-- deconstruct new_left <--- empty

		put_over :: a -> State (Nonempty List a) ()
		put_over = void . modify @State . item @Push

instance Morphable (Rotate Right) (Turnover < Tape List) where
	type Morphing (Rotate Right) (Turnover < Tape List) = Turnover < Tape List
	morphing s@(lower . run . premorph -> T_U (Exactly x :*: T_U (Reverse left :*: right))) =
		resolve @(Tape List _) <--- Turnover <--- premorph s
			<---- (rotate_over x <-|- run left) .-+- (rotate_right x left <-|- run right) where

		rotate_right :: a -> List a -> Nonempty List a -> Tape List a
		rotate_right focused ls (Construct rx rxs) = imply @(Tape List _) <-- rx <-- item @Push focused ls <-- TT rxs

		rotate_over :: a -> Nonempty List a -> Tape List a
		rotate_over focused ls = let new_right = attached (run <-- put_over <<- ls <-- point focused) in
			imply @(Tape List _) <--- extract new_right <--- empty <--- TT <-- deconstruct new_right

		put_over :: a -> State (Nonempty List a) ()
		put_over = void . modify @State . item @Push

instance Morphable (Into > Tape List) List where
	type Morphing (Into > Tape List) List = Maybe <::> Tape List
	morphing (premorph -> list) = (into @(Zipper List) <-|-) =#- list

instance Morphable (Into List) (Tape List) where
	type Morphing (Into List) (Tape List) = List
	morphing (lower . premorph -> T_U (Exactly x :*: T_U (Reverse left :*: right))) = attached <---- run @(->) @(State _)
		<--- modify @State . item @Push @List <<-- right
		<--- item @Push x left

instance Morphable (Into > Comprehension Maybe) (Tape List) where
	type Morphing (Into > Comprehension Maybe) (Tape List) = Comprehension Maybe
	morphing (lower . premorph -> T_U (Exactly x :*: T_U (Reverse left :*: right))) = attached <---- run @(->) @(State _)
		<--- modify @State . item @Push @(Comprehension Maybe) <<-- right
		<--- item @Push x <-- Comprehension left

------------------------------------- Zipper of non-empty list -------------------------------------

instance Zippable (Construction Maybe) where
	type Breadcrumbs (Construction Maybe) = Reverse > Construction Maybe <:.:> Construction Maybe > (:*:)

instance Morphable (Rotate Left) (Tape > Construction Maybe) where
	type Morphing (Rotate Left) (Tape > Construction Maybe) = Maybe <::> (Tape > Construction Maybe)
	morphing (lower . premorph -> T_U (Exactly x :*: T_U (Reverse left :*: right))) =
		TT <----- imply @(Tape (Nonempty List) _)
			<-|-- point <-- extract left
			<-*-- deconstruct left
			<-*-- point <-- item @Push x right

instance Morphable (Rotate Right) (Tape > Construction Maybe) where
	type Morphing (Rotate Right) (Tape > Construction Maybe) = Maybe <::> Tape (Construction Maybe)
	morphing (lower . premorph -> T_U (Exactly x :*: T_U (Reverse left :*: right))) =
		TT <----- imply @(Tape (Nonempty List) _)
			<-|-- point <-- extract right
			<-*-- point <-- item @Push x left
			<-*-- deconstruct right

instance Morphable (Into > Tape List) (Construction Maybe) where
	type Morphing (Into > Tape List) (Construction Maybe) = Tape List
	morphing (premorph -> ne) = imply @(Tape List _) <--- extract ne <--- empty <--- TT <-- deconstruct ne

--instance Morphable (Into > Tape List) (Tape > Construction Maybe) where
	--type Morphing (Into > Tape List) (Tape > Construction Maybe) = Tape List
	--morphing (premorph -> zipper) = (((((((lift =#-) :*: lift) <-|-<-|-) =#-) <-|-) =#-) =#-) zipper

--instance Morphable (Into > Tape > Construction Maybe) (Tape List) where
	--type Morphing (Into > Tape > Construction Maybe) (Tape List) =
		--Maybe <::> Tape (Construction Maybe)
	--morphing (lower . premorph -> zipper) = let spread x y = (\x' y' -> Reverse x' :*: y') <-|- x <-*- y in
		--lift . TT <--- T_U . (Exactly <-- extract zipper :*:) . T_U <-|- ((spread |-) . ((run . run :*: run) <-|-<-|-) . run . extract <-- run zipper)

instance Morphable (Into > Construction Maybe) (Tape > Construction Maybe) where
	type Morphing (Into > Construction Maybe) (Tape > Construction Maybe) = Construction Maybe
	morphing (lower . premorph -> T_U (Exactly x :*: T_U (Reverse left :*: right))) = attached <---- run @(->) @(State _)
		<--- modify @State . item @Push @(Nonempty List) <<-- right
		<--- item @Push x left

instance Morphable (Into List) (Tape > Construction Maybe) where
	type Morphing (Into List) (Tape > Construction Maybe) = List
	morphing (lower . premorph -> T_U (Exactly x :*: T_U (Reverse left :*: right))) = attached <---- run @(->) @(State _)
		<--- modify @State . item @Push @List <<-- right
		<--- item @Push x <-- lift left

------------------------------------ Zipper of combinative list ------------------------------------

instance Zippable (Comprehension Maybe) where
	type Breadcrumbs (Comprehension Maybe) = Comprehension Maybe <:.:> Comprehension Maybe > (:*:)

----------------------------------------- Prefixed list --------------------------------------------

instance Setoid key => Morphable (Lookup Key) (Prefixed List key) where
	type Morphing (Lookup Key) (Prefixed List key) = (->) key <::> Maybe
	morphing (run . premorph -> list) = TT <-- \key -> lookup @Key key ===<< Prefixed <-|- run list

------------------------------------ Prefixed non-empty list ---------------------------------------

instance Setoid key => Morphable (Lookup Key) (Prefixed < Construction Maybe < key) where
	type Morphing (Lookup Key) (Prefixed < Construction Maybe < key) = (->) key <::> Maybe
	morphing (run . premorph -> Construct x xs) = TT <-- \key -> extract <-|- search key where
		search key = key ?== attached x <----- Just x 
			<----- find @Element <--- Predicate <-- (key ==) . attached ====<< xs