{-# LANGUAGE UndecidableInstances, ScopedTypeVariables, TemplateHaskell, FlexibleInstances #-}
module AST.Knot.Prune
( Prune(..)
) where
import AST
import AST.Class.Traversable
import AST.Class.Unify (Unify)
import AST.Combinator.Compose (Compose(..))
import AST.Infer
import AST.Unify.New (newUnbound)
import AST.TH.Internal.Instances (makeCommonInstances)
import qualified Control.Lens as Lens
import Control.Lens.Operators
import Data.Constraint (Dict(..), withDict)
import Data.Proxy (Proxy(..))
import GHC.Generics (Generic)
import Prelude.Compat
data Prune k =
Pruned | Unpruned (k # Prune)
deriving Generic
makeCommonInstances [''Prune]
Lens.makePrisms ''Prune
makeKTraversableAndBases ''Prune
makeZipMatch ''Prune
instance KPointed Prune where
pureK f = Unpruned (f W_Prune_Prune)
instance KApply Prune where
zipK Pruned _ = Pruned
zipK _ Pruned = Pruned
zipK (Unpruned x) (Unpruned y) = Pair x y & Unpruned
instance RNodes Prune
instance c Prune => Recursively c Prune
instance RTraversable Prune
type instance InferOf (Compose Prune t) = InferOf t
instance
( Infer m t
, KPointed (InferOf t)
, KTraversable (InferOf t)
) =>
Infer m (Compose Prune t) where
inferBody (MkCompose Pruned) =
withDict (inferContext (Proxy @m) (Proxy @t)) $
pureK (Proxy @(Unify m) #> MkContainedK newUnbound)
& sequenceK
<&> (MkCompose Pruned, )
inferBody (MkCompose (Unpruned (MkCompose x))) =
mapK
( \_ (MkCompose (InferChild i)) ->
i <&> (\(InferredChild r t) -> InferredChild (MkCompose r) t)
& InferChild
) x
& inferBody
<&> Lens._1 %~ MkCompose . Unpruned . MkCompose
inferContext m t = withDict (inferContext m t) Dict