{-# OPTIONS_GHC -fno-warn-orphans #-} module Pandora.Paradigm.Structure.Binary (Binary, insert) where import Pandora.Core.Morphism ((&), (%), (!)) import Pandora.Pattern.Category ((.)) import Pandora.Pattern.Functor.Covariant (Covariant ((<$>), (<$$>))) import Pandora.Pattern.Functor.Pointable (Pointable (point)) import Pandora.Pattern.Functor.Traversable (Traversable ((->>), (->>>))) import Pandora.Pattern.Functor.Extractable (extract) import Pandora.Pattern.Functor.Divariant (($)) import Pandora.Pattern.Object.Chain (Chain ((<=>)), order) import Pandora.Paradigm.Basis.Maybe (Maybe (Just, Nothing), maybe) import Pandora.Paradigm.Basis.Product (Product ((:*:))) import Pandora.Paradigm.Basis.Wye (Wye (End, Left, Right, Both)) import Pandora.Paradigm.Basis.Twister (Twister (Twister)) import Pandora.Paradigm.Basis.Tagged (Tagged (Tag), type (:#)) import Pandora.Paradigm.Controlflow.Joint.Schemes.UT (UT (UT)) import Pandora.Paradigm.Controlflow.Joint.Interpreted (run) import Pandora.Paradigm.Inventory.Store (Store (Store)) import Pandora.Paradigm.Inventory.Optics ((%~)) import Pandora.Paradigm.Structure.Variation.Nonempty (Nonempty) import Pandora.Paradigm.Structure.Variation.Substructure (Substructure (Output, sub)) type Binary = UT Covariant Covariant (Twister Wye) Maybe instance Covariant Binary where f <$> UT g = UT $ f <$$> g instance Pointable Binary where point x = UT . Just . Twister x $ End instance Traversable Binary where UT g ->> f = UT <$> g ->>> f insert :: Chain a => a -> Binary a -> Binary a insert x (UT Nothing) = point x insert x tree@(UT (Just (Twister y _))) = x <=> y & order (sub @'Left %~ (insert x <$>) $ tree) tree (sub @'Right %~ (insert x <$>) $ tree) instance Substructure 'Left Binary where type Output 'Left Binary a = 'Left :# Binary a sub (UT Nothing) = Store $ (:*:) (Tag $ UT Nothing) $ (UT Nothing !) sub t@(UT (Just (Twister x End))) = Store $ (:*:) (Tag $ UT Nothing) $ maybe t (UT . Just . Twister x . Left) . run . extract sub (UT (Just (Twister x (Left lst)))) = Store $ (:*:) (Tag . UT . Just $ lst) $ maybe (point x) (UT . Just . Twister x . Left) . run . extract sub t@(UT (Just (Twister x (Right rst)))) = Store $ (:*:) (Tag $ UT Nothing) $ maybe t (UT . Just . Twister x . Both % rst) . run . extract sub (UT (Just (Twister x (Both lst rst)))) = Store $ (:*:) (Tag . UT . Just $ lst) $ maybe (UT (Just (Twister x (Right rst)))) (UT . Just . Twister x . Both % rst) . run . extract instance Substructure 'Right Binary where type Output 'Right Binary a = 'Right :# Binary a sub (UT Nothing) = Store $ Tag (UT Nothing) :*: (!) (UT Nothing) sub t@(UT (Just (Twister x End))) = Store $ (:*:) (Tag $ UT Nothing) $ maybe t (UT . Just . Twister x . Right) . run . extract sub t@(UT (Just (Twister x (Left lst)))) = Store $ (:*:) (Tag $ UT Nothing) $ maybe t (UT . Just . Twister x . Both lst) . run . extract sub (UT (Just (Twister x (Right rst)))) = Store $ (:*:) (Tag . UT . Just $ rst) $ maybe (point x) (UT . Just . Twister x . Right) . run . extract sub (UT (Just (Twister x (Both lst rst)))) = Store $ (:*:) (Tag . UT . Just $ rst) $ maybe (UT (Just (Twister x (Left lst)))) (UT . Just . Twister x . Both lst) . run . extract type instance Nonempty Binary = Twister Wye instance Substructure 'Left (Twister Wye) where type Output 'Left (Twister Wye) a = Maybe ('Left :# Twister Wye a) sub (Twister x End) = Store $ (:*:) Nothing $ (Twister x End !) sub (Twister x (Left lst)) = Store $ (:*:) (Just . Tag $ lst) $ maybe (Twister x End) (Twister x . Left . extract) sub tree@(Twister x (Right rst)) = Store $ (:*:) Nothing $ maybe tree (Twister x . Both % rst . extract) sub (Twister x (Both lst rst)) = Store $ (:*:) (Just . Tag $ lst) $ maybe (Twister x $ Right rst) (Twister x . Both % rst . extract) instance Substructure 'Right (Twister Wye) where type Output 'Right (Twister Wye) a = Maybe ('Right :# Twister Wye a) sub (Twister x End) = Store $ (:*:) Nothing $ (Twister x End !) sub tree@(Twister x (Left lst)) = Store $ (:*:) Nothing $ maybe tree (Twister x . Both lst . extract) sub (Twister x (Right rst)) = Store $ (:*:) (Just . Tag $ rst) $ maybe (Twister x End) (Twister x . Right . extract) sub (Twister x (Both lst rst)) = Store $ (:*:) (Just . Tag $ rst) $ maybe (Twister x $ Left lst) (Twister x . Both lst . extract)