Fixed larger bug

where pattern matching on `Just a` with type `Maybe b` could be used for
 any type.
This commit is contained in:
sebastian 2023-03-21 22:02:28 +01:00
parent 509de4415e
commit 57fe8cd0a6
2 changed files with 14 additions and 24 deletions

View file

@ -290,18 +290,12 @@ algoW = \case
(s2, t2, e1') <- algoW e1 (s2, t2, e1') <- algoW e1
let composition = s2 `compose` s1 let composition = s2 `compose` s1
return (composition, t2, apply composition $ T.ELet (T.Bind (name, t2) e0') e1') return (composition, t2, apply composition $ T.ELet (T.Bind (name, t2) e0') e1')
-- TODO: give caseExpr a concrete type before proceeding
-- probably by returning substitutions in the functions used in this body
ECase caseExpr injs -> do ECase caseExpr injs -> do
(sub, t, e') <- algoW caseExpr (sub, t, e') <- algoW caseExpr
(subst, inj_t, ret_t) <- checkCase t injs (subst, injs, ret_t) <- checkCase t injs
let composition = subst `compose` sub let composition = subst `compose` sub
let t' = apply composition t let t' = apply composition ret_t
trace ("COMPOSITION: " ++ show composition) return () return (composition, t', T.ECase t' e' injs)
trace ("T: " ++ show t) return ()
trace ("T': " ++ show t') return ()
return (composition, t', T.ECase t' e' (map (\(Inj i _) -> T.Inj (i, inj_t) e') injs))
-- | Unify two types producing a new substitution -- | Unify two types producing a new substitution
unify :: Type -> Type -> Infer Subst unify :: Type -> Type -> Infer Subst
@ -349,7 +343,7 @@ I.E. { a = a -> b } is an unsolvable constraint since there is no substitution
where these are equal where these are equal
-} -}
occurs :: Ident -> Type -> Infer Subst occurs :: Ident -> Type -> Infer Subst
occurs i t@(TPol a) = return (M.singleton i t) occurs i t@(TPol _) = return (M.singleton i t)
occurs i t = occurs i t =
if S.member i (free t) if S.member i (free t)
then then
@ -479,22 +473,22 @@ insertConstr i t =
-------- PATTERN MATCHING --------- -------- PATTERN MATCHING ---------
checkCase :: Type -> [Inj] -> Infer (Subst, Type, Type) checkCase :: Type -> [Inj] -> Infer (Subst, [T.Inj], Type)
checkCase expT injs = do checkCase expT injs = do
(injs, returns) <- mapAndUnzipM checkInj injs (injTs, injs, returns) <- unzip3 <$> mapM checkInj injs
(sub, injs_type) <- foldM (\(sub, acc) x -> (\a -> (a `compose` sub, a `apply` acc)) <$> unify x acc) (nullSubst, expT) injs (sub1, _) <- foldM (\(sub, acc) x -> (\a -> (a `compose` sub, a `apply` acc)) <$> unify x acc) (nullSubst, expT) injTs
(_, returns_type) <- foldM (\(sub, acc) x -> (\a -> (a `compose` sub, a `apply` acc)) <$> unify x acc) (nullSubst, head returns) (tail returns) (sub2, returns_type) <- foldM (\(sub, acc) x -> (\a -> (a `compose` sub, a `apply` acc)) <$> unify x acc) (nullSubst, head returns) (tail returns)
return (sub, injs_type, returns_type) return (sub2 `compose` sub1, injs, returns_type)
{- | fst = type of init {- | fst = type of init
| snd = type of expr | snd = type of expr
-} -}
checkInj :: Inj -> Infer (Type, Type) checkInj :: Inj -> Infer (Type, T.Inj, Type)
checkInj (Inj it expr) = do checkInj (Inj it expr) = do
(initT, vars) <- inferInit it (initT, vars) <- inferInit it
let converted = map (second (Forall [])) vars let converted = map (second (Forall [])) vars
(exprT, _) <- withBindings converted (inferExp expr) (exprT, e) <- withBindings converted (inferExp expr)
return (initT, exprT) return (initT, T.Inj (it, initT) e, exprT)
inferInit :: Init -> Infer (Type, [T.Id]) inferInit :: Init -> Infer (Type, [T.Id])
inferInit = \case inferInit = \case
@ -508,7 +502,6 @@ inferInit = \case
Just (vs, ret) -> Just (vs, ret) ->
case length vars `compare` length vs of case length vars `compare` length vs of
EQ -> do EQ -> do
trace ("IDS AND TYPES: " ++ show (zip vars vs)) return ()
return (ret, zip vars vs) return (ret, zip vars vs)
_ -> throwError "Partial pattern match not allowed" _ -> throwError "Partial pattern match not allowed"
InitCatch -> (,mempty) <$> fresh InitCatch -> (,mempty) <$> fresh
@ -519,5 +512,3 @@ flattenType a = [a]
litType :: Literal -> Type litType :: Literal -> Type
litType (LInt _) = TMono "Int" litType (LInt _) = TMono "Int"
ctrace a = trace (show a) a

View file

@ -15,10 +15,9 @@ data Maybe ('a) where {
-- False => Just True -- False => Just True
-- }; -- };
fun : Maybe (_Int) -> _Int ; fun : Maybe ('a) -> 'a ;
fun a = fun a =
case a of { case a of {
Just b => b; Just c => c
Nothing => 0
}; };