module Data.Generics.ClassyPlate.Core
(
classyTraverse, classyTraverseM, selectiveTraverse, selectiveTraverseM, smartTraverse, smartTraverseM
, ClassyPlate, SmartClassyPlate
, classyTraverse_, classyTraverseM_, selectiveTraverse_, selectiveTraverseM_, smartTraverse_, smartTraverseM_
, app, appM, appIf, appIfM
, GoodOperationFor, GoodOperationForAuto, FlagToken
, MonoMatch (..)
) where
import GHC.Exts
import Data.Maybe
import GHC.Generics (Generic)
import Data.Data (Data)
import Data.Generics.ClassyPlate.TypePrune
type GoodOperationFor c e = (App (AppSelector c e) c e)
type GoodOperationForAuto c e = (GoodOperationFor c e, Generic e)
data ClsToken (c :: * -> Constraint)
data FlagToken (c :: Bool)
class App (flag :: Bool) c b where
app :: FlagToken flag -> ClsToken c -> (forall a . c a => a -> a) -> b -> b
appM :: Monad m => FlagToken flag -> ClsToken c -> (forall a . c a => a -> m a) -> b -> m b
appPred :: FlagToken flag -> ClsToken c -> (forall a . c a => a -> Bool) -> b -> b -> b
appPredM :: Monad m => FlagToken flag -> ClsToken c -> (forall a . c a => a -> m Bool) -> b -> m b -> m b
instance c b => App 'True c b where
app _ _ f a = f a
appM _ _ f a = f a
appPred _ _ f th el = if f th then el else th
appPredM _ _ f th el = f th >>= \p -> if p then el else return th
instance App 'False c b where
app _ _ _ a = a
appM _ _ _ a = return a
appPred _ _ _ _ el = el
appPredM _ _ _ _ el = el
class GoodOperationFor c b => ClassyPlate c b where
classyTraverse_ :: ClsToken c -> (forall a . c a => a -> a) -> b -> b
classyTraverseM_ :: Monad m => ClsToken c -> (forall a . c a => a -> m a) -> b -> m b
selectiveTraverse_ :: ClsToken c -> (forall a . c a => a -> a) -> (forall a . c a => a -> Bool) -> b -> b
selectiveTraverseM_ :: Monad m => ClsToken c -> (forall a . c a => a -> m a) -> (forall a . c a => a -> m Bool) -> b -> m b
class (GoodOperationForAuto c b) => SmartClassyPlate c (sel :: Bool) b where
smartTraverse_ :: FlagToken sel -> ClsToken c -> (forall a . c a => a -> a) -> b -> b
smartTraverseM_ :: Monad m => FlagToken sel -> ClsToken c -> (forall a . c a => a -> m a) -> b -> m b
classyTraverse :: forall c b . ClassyPlate c b => (forall a . c a => a -> a) -> b -> b
classyTraverse = classyTraverse_ (undefined :: ClsToken c)
classyTraverseM :: forall c b m . (ClassyPlate c b, Monad m) => (forall a . c a => a -> m a) -> b -> m b
classyTraverseM = classyTraverseM_ (undefined :: ClsToken c)
selectiveTraverse :: forall c b . ClassyPlate c b => (forall a . c a => a -> a) -> (forall a . c a => a -> Bool) -> b -> b
selectiveTraverse = selectiveTraverse_ (undefined :: ClsToken c)
selectiveTraverseM :: forall c b m . (ClassyPlate c b, Monad m) => (forall a . c a => a -> m a) -> (forall a . c a => a -> m Bool) -> b -> m b
selectiveTraverseM = selectiveTraverseM_ (undefined :: ClsToken c)
smartTraverse :: forall c b . SmartClassyPlate c (ClassIgnoresSubtree c b) b => (forall a . c a => a -> a) -> b -> b
smartTraverse = smartTraverse_ (undefined :: FlagToken (ClassIgnoresSubtree c b)) (undefined :: ClsToken c)
smartTraverseM :: forall c b m . (SmartClassyPlate c (ClassIgnoresSubtree c b) b, Monad m) => (forall a . c a => a -> m a) -> b -> m b
smartTraverseM = smartTraverseM_ (undefined :: FlagToken (ClassIgnoresSubtree c b)) (undefined :: ClsToken c)
instance (GoodOperationForAuto c b) => SmartClassyPlate c True b where
smartTraverse_ _ t f a = app (undefined :: FlagToken (AppSelector c b)) t f a
smartTraverseM_ _ t f a = appM (undefined :: FlagToken (AppSelector c b)) t f a
class MonoMatch a b where
monoApp :: (a -> a) -> b -> b
instance MonoMatch a a where
monoApp = id
type instance AppSelector (MonoMatch a) b = TypEq a b
type family TypEq a b :: Bool where
TypEq a a = 'True
TypEq a b = 'False
appIf :: forall c b . App (AppSelector c b) c b => ClsToken c -> (forall a . c a => a -> a) -> (forall a . c a => a -> Bool) -> b -> b -> b
appIf t f pred val combined = app flTok t f $ appPred flTok t pred val combined
where flTok = undefined :: FlagToken (AppSelector c b)
appIfM :: forall c b m . (App (AppSelector c b) c b, Monad m) => ClsToken c -> (forall a . c a => a -> m a) -> (forall a . c a => a -> m Bool) -> b -> m b -> m b
appIfM t f pred val combined = appM flTok t f =<< appPredM flTok t pred val combined
where flTok = undefined :: FlagToken (AppSelector c b)