{-# LANGUAGE AllowAmbiguousTypes #-}

module Pandora.Paradigm.Structure.Ability.Substructure where

import Pandora.Pattern.Category ((.))
import Pandora.Pattern.Functor.Covariant (comap)
import Pandora.Pattern.Functor.Extractable (extract)
import Pandora.Paradigm.Inventory.Optics (type (:-.))
import Pandora.Paradigm.Primary.Functor.Tagged (Tagged (Tag))

class Substructure f t where
	type Substructural (f :: * -> k) (t :: * -> *) a
	substructure :: Tagged f (t a) :-. Substructural f t a

sub :: forall f t a . Substructure f t => t a :-. Substructural f t a
sub :: t a :-. Substructural f t a
sub = (Tagged f (t a) -> t a)
-> Store (Substructural f t a) (Tagged f (t a))
-> Store (Substructural f t a) (t a)
forall (t :: * -> *) a b. Covariant t => (a -> b) -> t a -> t b
comap Tagged f (t a) -> t a
forall (t :: * -> *) a. Extractable t => a <-| t
extract (Store (Substructural f t a) (Tagged f (t a))
 -> Store (Substructural f t a) (t a))
-> (t a -> Store (Substructural f t a) (Tagged f (t a)))
-> t a :-. Substructural f t a
forall (m :: * -> * -> *) b c a.
Category m =>
m b c -> m a b -> m a c
. Tagged f (t a) :-. Substructural f t a
forall k (f :: * -> k) (t :: * -> *) a.
Substructure f t =>
Tagged f (t a) :-. Substructural f t a
substructure (Tagged f (t a) :-. Substructural f t a)
-> (t a -> Tagged f (t a))
-> t a
-> Store (Substructural f t a) (Tagged f (t a))
forall (m :: * -> * -> *) b c a.
Category m =>
m b c -> m a b -> m a c
. forall a. a -> Tagged f a
forall k (tag :: k) a. a -> Tagged tag a
Tag @f