Unify.hs revision 36c6cc568751e4235502cfee00ba7b597dae78dc
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel HausmannModule : $Header$
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel HausmannCopyright : (c) Christian Maeder and Uni Bremen 2003
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu ProdescuLicense : similar to LGPL, see HetCATS/LICENSE.txt or LIZENZ.txt
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel HausmannMaintainer : maeder@tzi.de
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel HausmannStability : experimental
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel HausmannPortability : portable
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmannsubstitution and unification of types
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmannimport qualified Common.Lib.Map as Map
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmannimport qualified Common.Lib.Set as Set
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmann-- | bound vars
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel HausmanngenVarsOf :: Type -> [(Id, RawKind)]
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel HausmanngenVarsOf = map snd . leaves (<0)
d024d9de9b6e7a7cfd72ef72d8efb0e57da5a01bChristian Maeder-- | vars or other ids
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmannleaves :: (Int -> Bool) -> Type -> [(Int, (Id, RawKind))]
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder TypeName j k i -> if b(i)
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmann then [(i, (j, k))]
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder TypeAppl t1 t2 -> leaves b t1 `List.union` leaves b t2
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder ExpandedType _ t2 -> leaves b t2
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder KindedType tk _ _ -> leaves b tk
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder LazyType tl _ -> leaves b tl
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder ProductType l _ -> foldl List.union [] $ map (leaves b) l
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder FunType t1 _ t2 _ -> leaves b t1 `List.union` leaves b t2
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder _ -> error ("leaves: " ++ show t)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder-- | composition (reversed: first substitution first!)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroedercompSubst :: Subst -> Subst -> Subst
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroedercompSubst s1 s2 = Map.union (Map.map (subst s2) s1) s2
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder-- | unifiability of type schemes including instantiation with fresh variables
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder-- (and looking up type aliases)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroederisUnifiable :: TypeMap -> Int -> TypeScheme -> TypeScheme -> Bool
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroederisUnifiable tm c = asSchemes c (unify tm)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder-- | test if second scheme is a substitution instance
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroederinstScheme :: TypeMap -> Int -> TypeScheme -> TypeScheme -> Bool
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroederinstScheme tm c = asSchemes c (subsume tm)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder-- | lift 'State' Int to 'State' Env
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroedertoEnvState :: State Int a -> State Env a
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmann let (r, c) = runState p $ counter s
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmann put s { counter = c }
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel HausmanntoSchemes :: (Type -> Type -> a) -> TypeScheme -> TypeScheme -> State Int a
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroedertoSchemes f sc1 sc2 =
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder do t1 <- freshInst sc1
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder t2 <- freshInst sc2
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder return $ f t1 t2
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroederasSchemes :: Int -> (Type -> Type -> a) -> TypeScheme -> TypeScheme -> a
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroederasSchemes c f sc1 sc2 = fst $ runState (toSchemes f sc1 sc2) c
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder-- -------------------------------------------------------------------------
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroederfreshInst :: TypeScheme -> State Int Type
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroederfreshInst (TypeScheme _ t _) =
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder do let ls = leaves (< 0) t -- generic vars
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder vs = map snd ls
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder ts <- mkSubst vs
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmann return $ subst (Map.fromList $ zip (map fst ls) ts) t
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmanninc :: State Int Int
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel HausmannfreshVar :: [Pos] -> State Int (Id, Int)
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel HausmannfreshVar ps = do
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel Hausmann return (simpleIdToId $ Token ("_var_" ++ show c) ps, c)
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel HausmannmkSingleSubst :: (Id, RawKind) -> State Int Type
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel HausmannmkSingleSubst (i, rk) = do
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel Hausmann (ty, c) <- freshVar $ posOfId i
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel Hausmann return $ TypeName ty rk c
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel HausmannmkSubst :: [(Id, RawKind)] -> State Int [Type]
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel HausmannmkSubst = mapM mkSingleSubst
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel Hausmanntype Subst = Map.Map Int Type
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroederclass Unifiable a where
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmann subst :: Subst -> a -> a
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmann match :: TypeMap -> (TypeId -> TypeId -> Bool)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder -> (Bool, a) -> (Bool, a) -> Result Subst
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroeder-- | most general unifier via 'match'
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmann-- where both sides may contribute substitutions
c8cc43106ea9a9bd1890ed81fc40b9877a4414d0Daniel Hausmannmgu :: Unifiable a => TypeMap -> a -> a -> Result Subst
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroedermgu tm a b = match tm (==) (True, a) (True, b)
093f1948e37cc2e9be32cae0a4913fc1bac0c84bDaniel HausmannshapeMatch :: Unifiable a => TypeMap -> a -> a -> Result Subst
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von SchroedershapeMatch tm a b = match tm (const $ const True) (True, a) (True, b)
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroederunify :: Unifiable a => TypeMap -> a -> a -> Bool
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroederunify tm a b = isJust $ maybeResult $ mgu tm a b
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroedersubsume :: Unifiable a => TypeMap -> a -> a -> Bool
3d3889e0cefcdce9b3f43c53aaa201943ac2e895Jonathan von Schroedersubsume tm a b =
idsOf :: (Int -> Bool) -> Type -> Set.Set TypeId
idsOf b = Set.fromList . map (fst . snd) . leaves b
case Map.lookup n m of
Map.singleton v1 t2
Map.singleton v2 t1
return $ Map.singleton v1 t2
repl :: Map.Map Id Type -> Type -> Type
case Map.lookup i m of
ExpandedType t $ repl (Map.fromList (zip
TypeName i _ _ -> case Map.lookup i tm of