module MagicHaskeller.Analytical.UniT where
import Control.Monad
import Control.Monad.State
import MagicHaskeller.Analytical.Syntax
type UniT a = StateT (St a)
data St a = St {subst::Subst a, nextVar :: Int} deriving Show
emptySt = St {subst=[], nextVar=0}
freshIOP (IOP n ins out) = do st <- get
let nv = nextVar st
put st{nextVar = nv + n}
return $ IOP 0 (map (fresh (nv+)) ins) (fresh (nv+) out)
applyUT :: Monad m => Expr a -> UniT a m (Expr a)
applyUT ex = do s <- gets subst
return $ apply s ex
applyIOPUT iop = do s <- gets subst
return $ applyIOP s iop
unifyUT :: MonadPlus m => Expr a -> Expr a -> UniT a m ()
unifyUT e1 e2 = case unify e1 e2 of Just s -> modify (\st -> st{subst = s `plusSubst` subst st})
Nothing -> mzero
appUnifyUT e1 e2 = do s <- gets subst
unifyUT (apply s e1) (apply s e2)