hypertypes-0.2.2: src/Hyper/Unify/Binding/Save.hs
{-# LANGUAGE FlexibleContexts #-}
-- | Serialize the state of unification
module Hyper.Unify.Binding.Save
( save
) where
import qualified Control.Lens as Lens
import Control.Monad.Trans.Class (MonadTrans (..))
import Control.Monad.Trans.State (StateT (..))
import Hyper
import Hyper.Class.Optic (HNodeLens (..))
import Hyper.Class.Unify (BindingDict (..), UVarOf, Unify (..))
import Hyper.Recurse
import Hyper.Unify.Binding (Binding, UVar (..), _Binding)
import Hyper.Unify.Term (UTerm (..), uBody)
import Hyper.Internal.Prelude
saveUTerm ::
forall m typeVars t.
(Unify m t, Recursively (HNodeLens typeVars) t) =>
UTerm (UVarOf m) # t ->
StateT (typeVars # Binding, [m ()]) m (UTerm UVar # t)
saveUTerm (UUnbound c) = UUnbound c & pure
saveUTerm (USkolem c) = USkolem c & pure
saveUTerm (UToVar v) = saveVar v <&> UToVar
saveUTerm (UTerm u) = uBody saveBody u <&> UTerm
saveUTerm UInstantiated{} = error "converting bindings during instantiation"
saveUTerm UResolving{} = error "converting bindings after resolution"
saveUTerm UResolved{} = error "converting bindings after resolution"
saveUTerm UConverted{} = error "converting variable again"
saveVar ::
forall m t typeVars.
(Unify m t, Recursively (HNodeLens typeVars) t) =>
UVarOf m # t ->
StateT (typeVars # Binding, [m ()]) m (UVar # t)
saveVar v =
lookupVar binding v
& lift
>>= \case
UConverted i -> pure (UVar i)
srcBody ->
do
pb <- Lens.use (Lens._1 . hNodeLens)
let r = pb ^. _Binding & length
UConverted r & bindVar binding v & lift
Lens._2 %= (<> [bindVar binding v srcBody])
dstBody <- saveUTerm srcBody
Lens._1 . hNodeLens .= (pb & _Binding %~ (Lens.|> dstBody))
UVar r & pure
\\ recursively (Proxy @(HNodeLens typeVars t))
saveBody ::
forall m typeVars t.
(Unify m t, Recursively (HNodeLens typeVars) t) =>
t # UVarOf m ->
StateT (typeVars # Binding, [m ()]) m (t # UVar)
saveBody =
htraverse
( Proxy @(Unify m) #*#
Proxy @(Recursively (HNodeLens typeVars)) #>
saveVar
)
\\ recurse (Proxy @(Unify m t))
\\ recursively (Proxy @(HNodeLens typeVars t))
-- | Serialize the state of unification for
-- the unification variables in a given value,
-- and transform the value's unification variables
-- to their serialized identifiers.
save ::
(Unify m t, Recursively (HNodeLens typeVars) t) =>
t # UVarOf m ->
StateT (typeVars # Binding) m (t # UVar)
save collection =
StateT $
\dstState ->
do
(r, (finalState, recover)) <- runStateT (saveBody collection) (dstState, [])
(r, finalState) <$ sequence_ recover