pandora-0.5.0: Pandora/Paradigm/Structure/Some/List.hs
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Pandora.Paradigm.Structure.Some.List where
import Pandora.Core.Functor (type (:.), type (:=))
import Pandora.Core.Impliable (imply)
import Pandora.Pattern.Semigroupoid ((.))
import Pandora.Pattern.Category ((#), identity)
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.Object.Boolean (Boolean (True, False))
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.Functor.Maybe (Maybe (Just, Nothing))
import Pandora.Paradigm.Primary.Functor.Identity (Identity (Identity))
import Pandora.Paradigm.Primary.Functor.Predicate (Predicate (Predicate))
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.Modifiable (Modifiable (Modification, 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.Conditional (Conditional ((?)))
import Pandora.Paradigm.Controlflow.Effect.Interpreted (run, (!), (||=))
import Pandora.Paradigm.Schemes.TT (TT (TT), type (<::>))
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.Nullable (Nullable (null))
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 (Available, Substance, substructure, sub), Segment (Root, Tail))
import Pandora.Paradigm.Structure.Interface.Stack (Stack)
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 = Identity <:.:> 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 -> run p x ? 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 ! \_ -> empty
Just (Construct x xs) -> T_U ! \p ->
run p x ? 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 ! \_ -> empty
Just (Construct x xs) -> T_U ! \p ->
run p x ? filter @All @List p (TT xs)
! lift . Construct x . run . filter @All @List p # TT xs
instance Stack List where
instance Nullable List where
null = Predicate ! \case { TT Nothing -> True ; _ -> False }
instance Substructure Root List where
type Available Root List = Maybe
type Substance Root List = Identity
substructure = P_Q_T ! \zipper -> case run # lower zipper of
Just (Construct x xs) -> Store ! Just (Identity x) :*: lift . resolve (lift . (Construct % xs) . extract @Identity) zero
Nothing -> Store ! Nothing :*: lift . resolve (lift . (Construct % Nothing) . extract @Identity) zero
instance Substructure Tail List where
type Available Tail List = Identity
type Substance Tail List = List
substructure = P_Q_T ! \x -> case run . extract . run ! x of
Just ns -> lift . lift @(->) <-|- run (sub @Tail) ns
Nothing -> Store ! Identity zero :*: lift . identity . extract
-- | Transform any traversable structure into a stack
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 ->
run p x ? 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) = Identity <:.:> Construction Maybe := (->)
morphing (premorph -> xs) = T_U ! \(Identity x) -> Construct x ! Just xs
instance Substructure Root (Construction Maybe) where
type Available Root (Construction Maybe) = Identity
type Substance Root (Construction Maybe) = Identity
substructure = imply @(Convex Lens _ _) (Identity . extract . lower)
(\source target -> lift (Construct # extract target # deconstruct (lower source)))
instance Substructure Tail (Construction Maybe) where
type Available Tail (Construction Maybe) = Identity
type Substance Tail (Construction Maybe) = List
substructure = imply @(Convex Lens _ _) (TT . deconstruct . lower)
(\source target -> lift (Construct # extract (lower source) # run target))
---------------------------------------- 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 <<- T_U (Identity x :*: T_U (left :*: right)) = (\past' x' left' -> twosome (Identity 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
twosome (Identity # f z) ! twosome # Reverse (f <-|- move (rotate @Left)) # f <-|- move (rotate @Right)
instance Morphable (Rotate Left) (Tape List) where
type Morphing (Rotate Left) (Tape List) = Maybe <::> Tape List
morphing (premorph -> T_U (Identity x :*: T_U (Reverse left :*: right))) =
let subtree = twosome # Reverse (get @(Convex Lens) # sub @Tail # left) # item @Push x right in
TT ! (twosome . Identity . extract) % subtree <-|- get @(Obscure Lens) (sub @Root) left
instance Morphable (Rotate Right) (Tape List) where
type Morphing (Rotate Right) (Tape List) = Maybe <::> Tape List
morphing (premorph -> T_U (Identity x :*: T_U (Reverse left :*: right))) =
let subtree = twosome # Reverse (item @Push x left) # get @(Convex Lens) (sub @Tail) right in
TT ! twosome % subtree <-|- get @(Obscure Lens) (sub @Root) right
instance Morphable (Rotate Left) (Turnover (Tape List)) where
type Morphing (Rotate Left) (Turnover (Tape List)) = Turnover (Tape List)
morphing s@(premorph -> Turnover (T_U (Identity 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) = twosome # point lx
! twosome # Reverse (TT lxs) # item @Push focused rs
rotate_over :: a -> Nonempty List a -> Tape List a
rotate_over focused rs = let new_left = attached (put_over <<- rs ! point focused) in
twosome # point (extract new_left) ! twosome (Reverse . 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@(premorph -> Turnover (T_U (Identity 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) = twosome # point rx
! twosome # Reverse (item @Push focused ls) # TT rxs
rotate_over :: a -> Nonempty List a -> Tape List a
rotate_over focused ls = let new_right = attached (put_over <<- ls ! point focused) in
twosome # point (extract new_right) ! twosome (Reverse 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 (premorph -> T_U (Identity 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 (premorph -> T_U (Identity 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 (premorph -> T_U (Identity x :*: T_U (Reverse left :*: right))) =
TT ! T_U . (Identity (extract left) :*:) . (twosome % item @Push x right) . Reverse <-|- deconstruct left
instance Morphable (Rotate Right) (Tape (Construction Maybe)) where
type Morphing (Rotate Right) (Tape (Construction Maybe)) =
Maybe <::> Tape (Construction Maybe)
morphing (premorph -> T_U (Identity x :*: T_U (Reverse left :*: right))) =
TT ! T_U . (Identity (extract right) :*:) . twosome (Reverse # 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) = twosome # Identity (extract ne) ! twosome # Reverse zero # (get @(Convex Lens) # sub @Tail # 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 (premorph -> zipper) = let spread x y = (\x' y' -> Reverse x' :*: y') <-|- x <-*- y in
TT ! T_U . (Identity (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 (premorph -> T_U (Identity 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 (premorph -> T_U (Identity 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