@@ -151,17 +151,17 @@ typesOf moduleName vals = do
151 typedDict = map (\(ident, (_, Just ty)) -> (ident, ty)) typed
151 typedDict = map (\(ident, (_, Just ty)) -> (ident, ty)) typed
152 untypedNames <- replicateM (length untyped) fresh
152 untypedNames <- replicateM (length untyped) fresh
153 let untypedDict = zip (map fst untyped) untypedNames
153 let untypedDict = zip (map fst untyped) untypedNames
154− dict = M.fromList (map (\(ident, ty) -> ((moduleName, ident), (ty, LocalVariable))) $ typedDict ++ untypedDict)
154+ dict = M.fromList (map (\(ident, ty) -> ((moduleName, ident), (ty, LocalVariable))) $ (map (id *** fst) typedDict) ++ untypedDict)
155 forM es $ \e -> do
155 forM es $ \e -> do
156 triple@(_, (val, ty)) <- case e of
156 triple@(_, (val, ty)) <- case e of
157− (ident, (val, Just ty)) -> do
157+ (ident, (val, Just (ty, checkType))) -> do
158 kind <- liftCheck $ kindOf moduleName ty
158 kind <- liftCheck $ kindOf moduleName ty
159 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
159 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
160 ty' <- replaceAllTypeSynonyms ty
160 ty' <- replaceAllTypeSynonyms ty
161− val' <- bindNames dict $ check val ty'
161+ val' <- bindNames dict $ if checkType then check val ty' else return val
162 return (ident, (val', ty'))
162 return (ident, (val', ty'))
163 (ident, (val, Nothing)) -> do
163 (ident, (val, Nothing)) -> do
164− TypedValue val' ty <- bindNames dict $ infer val
164+ TypedValue _ val' ty <- bindNames dict $ infer val
165 ty ~~ fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
165 ty ~~ fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
166 return (ident, (val', ty))
166 return (ident, (val', ty))
167 when (moduleName == ModuleName (ProperName "Main") && fst e == Ident "main") $ do
167 when (moduleName == ModuleName (ProperName "Main") && fst e == Ident "main") $ do
@@ -175,8 +175,8 @@ typesOf moduleName vals = do
175 return (ident, (overTypes (desaturateAllTypeSynonyms . setifyAll) $ val'
175 return (ident, (overTypes (desaturateAllTypeSynonyms . setifyAll) $ val'
176 , varIfUnknown . desaturateAllTypeSynonyms . setifyAll $ ty))
176 , varIfUnknown . desaturateAllTypeSynonyms . setifyAll $ ty))
178−isTyped :: (Ident, Value) -> (Ident, (Value, Maybe Type))
178+isTyped :: (Ident, Value) -> (Ident, (Value, Maybe (Type, Bool)))
179−isTyped (name, TypedValue value ty) = (name, (value, Just ty))
179+isTyped (name, TypedValue checkType value ty) = (name, (value, Just (ty, checkType)))
180isTyped (name, value) = (name, (value, Nothing))
180isTyped (name, value) = (name, (value, Nothing))
182overTypes :: (Type -> Type) -> Value -> Value
182overTypes :: (Type -> Type) -> Value -> Value
@@ -231,7 +231,7 @@ escapeCheck value ty = do
231findAllTypes :: Value -> [Type]
231findAllTypes :: Value -> [Type]
232findAllTypes = everything (++) (mkQ [] go)
232findAllTypes = everything (++) (mkQ [] go)
234− go (TypedValue _ ty) = [ty]
234+ go (TypedValue _ _ ty) = [ty]
235 go _ = []
235 go _ = []
237skolemEscapeCheck :: Type -> Check ()
237skolemEscapeCheck :: Type -> Check ()
@@ -299,14 +299,14 @@ infer :: Value -> Subst Value
299infer val = rethrow (\e -> "Error inferring type of term " ++ prettyPrintValue val ++ ":\n" ++ e) $ infer' val
299infer val = rethrow (\e -> "Error inferring type of term " ++ prettyPrintValue val ++ ":\n" ++ e) $ infer' val
301infer' :: Value -> Subst Value
301infer' :: Value -> Subst Value
302−infer' v@(NumericLiteral _) = return $ TypedValue v Number
302+infer' v@(NumericLiteral _) = return $ TypedValue True v Number
303−infer' v@(StringLiteral _) = return $ TypedValue v String
303+infer' v@(StringLiteral _) = return $ TypedValue True v String
304−infer' v@(BooleanLiteral _) = return $ TypedValue v Boolean
304+infer' v@(BooleanLiteral _) = return $ TypedValue True v Boolean
305infer' (ArrayLiteral vals) = do
305infer' (ArrayLiteral vals) = do
306 ts <- mapM infer vals
306 ts <- mapM infer vals
307 els <- fresh
307 els <- fresh
308− forM_ ts $ \(TypedValue _ t) -> els ~~ Array t
308+ forM_ ts $ \(TypedValue _ _ t) -> els ~~ Array t
309− return $ TypedValue (ArrayLiteral ts) els
309+ return $ TypedValue True (ArrayLiteral ts) els
310infer' (Unary op val) = do
310infer' (Unary op val) = do
311 v <- infer val
311 v <- infer val
312 inferUnary op v
312 inferUnary op v
@@ -317,43 +317,43 @@ infer' (Binary op left right) = do
317infer' (ObjectLiteral ps) = do
317infer' (ObjectLiteral ps) = do
318 ensureNoDuplicateProperties ps
318 ensureNoDuplicateProperties ps
319 ts <- mapM (infer . snd) ps
319 ts <- mapM (infer . snd) ps
320− let fields = zipWith (\name (TypedValue _ t) -> (name, t)) (map fst ps) ts
320+ let fields = zipWith (\name (TypedValue _ _ t) -> (name, t)) (map fst ps) ts
321 ty = Object $ rowFromList (fields, REmpty)
321 ty = Object $ rowFromList (fields, REmpty)
322− return $ TypedValue (ObjectLiteral (zip (map fst ps) ts)) ty
322+ return $ TypedValue True (ObjectLiteral (zip (map fst ps) ts)) ty
323infer' (ObjectUpdate o ps) = do
323infer' (ObjectUpdate o ps) = do
324 ensureNoDuplicateProperties ps
324 ensureNoDuplicateProperties ps
325 row <- fresh
325 row <- fresh
326 newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> mapM (infer . snd) ps
326 newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> mapM (infer . snd) ps
327− let newTys = map (\(name, TypedValue _ ty) -> (name, ty)) newVals
327+ let newTys = map (\(name, TypedValue _ _ ty) -> (name, ty)) newVals
328 oldTys <- zip (map fst ps) <$> replicateM (length ps) fresh
328 oldTys <- zip (map fst ps) <$> replicateM (length ps) fresh
329 o' <- check o $ Object $ rowFromList (oldTys, row)
329 o' <- check o $ Object $ rowFromList (oldTys, row)
330− return $ TypedValue (ObjectUpdate o' newVals) $ Object $ rowFromList (newTys, row)
330+ return $ TypedValue True (ObjectUpdate o' newVals) $ Object $ rowFromList (newTys, row)
331infer' (Indexer index val) = do
331infer' (Indexer index val) = do
332 el <- fresh
332 el <- fresh
333 index' <- check index Number
333 index' <- check index Number
334 val' <- check val (Array el)
334 val' <- check val (Array el)
335− return $ TypedValue (Indexer (TypedValue index' Number) (TypedValue val' (Array el))) el
335+ return $ TypedValue True (Indexer (TypedValue True index' Number) (TypedValue True val' (Array el))) el
336infer' (Accessor prop val) = do
336infer' (Accessor prop val) = do
337− typed@(TypedValue _ objTy) <- infer val
337+ typed@(TypedValue _ _ objTy) <- infer val
338 propTy <- inferProperty objTy prop
338 propTy <- inferProperty objTy prop
339 case propTy of
339 case propTy of
340 Nothing -> do
340 Nothing -> do
341 field <- fresh
341 field <- fresh
342 rest <- fresh
342 rest <- fresh
343 objTy `subsumes` Object (RCons prop field rest)
343 objTy `subsumes` Object (RCons prop field rest)
344− return $ TypedValue (Accessor prop typed) field
344+ return $ TypedValue True (Accessor prop typed) field
345− Just ty -> return $ TypedValue (Accessor prop typed) ty
345+ Just ty -> return $ TypedValue True (Accessor prop typed) ty
346infer' (Abs args ret) = do
346infer' (Abs args ret) = do
347 ts <- replicateM (length args) fresh
347 ts <- replicateM (length args) fresh
348 moduleName <- substCurrentModule <$> ask
348 moduleName <- substCurrentModule <$> ask
349 bindLocalVariables moduleName (zip args ts) $ do
349 bindLocalVariables moduleName (zip args ts) $ do
350− body@(TypedValue _ bodyTy) <- infer' ret
350+ body@(TypedValue _ _ bodyTy) <- infer' ret
351− return $ TypedValue (Abs args body) $ Function ts bodyTy
351+ return $ TypedValue True (Abs args body) $ Function ts bodyTy
352infer' (App f args) = do
352infer' (App f args) = do
353− f'@(TypedValue _ ft) <- infer f
353+ f'@(TypedValue _ _ ft) <- infer f
354 ret <- fresh
354 ret <- fresh
355 app <- checkFunctionApplication f' ft args ret
355 app <- checkFunctionApplication f' ft args ret
356− return $ TypedValue app ret
356+ return $ TypedValue True app ret
357infer' (Var var) = do
357infer' (Var var) = do
358 moduleName <- substCurrentModule <$> ask
358 moduleName <- substCurrentModule <$> ask
359 ty <- lookupVariable moduleName var
359 ty <- lookupVariable moduleName var
@@ -362,38 +362,38 @@ infer' (Var var) = do
362 ConstrainedType constraints _ -> do
362 ConstrainedType constraints _ -> do
363 env <- getEnv
363 env <- getEnv
364 dicts <- getTypeClassDictionaries
364 dicts <- getTypeClassDictionaries
365− return $ TypedValue (App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty'
365+ return $ TypedValue True (App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty'
366− _ -> return $ TypedValue (Var var) ty'
366+ _ -> return $ TypedValue True (Var var) ty'
367infer' (Block ss) = do
367infer' (Block ss) = do
368 ret <- fresh
368 ret <- fresh
369 (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
369 (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
370 guardWith "Block is missing a return statement" allCodePathsReturn
370 guardWith "Block is missing a return statement" allCodePathsReturn
371− return $ TypedValue (Block ss') ret
371+ return $ TypedValue True (Block ss') ret
372infer' v@(Constructor c) = do
372infer' v@(Constructor c) = do
373 env <- getEnv
373 env <- getEnv
374 moduleName <- substCurrentModule `fmap` ask
374 moduleName <- substCurrentModule `fmap` ask
375 case M.lookup (qualify moduleName c) (dataConstructors env) of
375 case M.lookup (qualify moduleName c) (dataConstructors env) of
376 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
376 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
377 Just (ty, _) -> do ty' <- replaceAllTypeSynonyms ty
377 Just (ty, _) -> do ty' <- replaceAllTypeSynonyms ty
378− return $ TypedValue v ty'
378+ return $ TypedValue True v ty'
379infer' (Case vals binders) = do
379infer' (Case vals binders) = do
380 ts <- mapM infer vals
380 ts <- mapM infer vals
381 ret <- fresh
381 ret <- fresh
382− binders' <- checkBinders (map (\(TypedValue _ t) -> t) ts) ret binders
382+ binders' <- checkBinders (map (\(TypedValue _ _ t) -> t) ts) ret binders
383− return $ TypedValue (Case ts binders') ret
383+ return $ TypedValue True (Case ts binders') ret
384infer' (IfThenElse cond th el) = do
384infer' (IfThenElse cond th el) = do
385 cond' <- check cond Boolean
385 cond' <- check cond Boolean
386− v2@(TypedValue _ t2) <- infer th
386+ v2@(TypedValue _ _ t2) <- infer th
387− v3@(TypedValue _ t3) <- infer el
387+ v3@(TypedValue _ _ t3) <- infer el
389− return $ TypedValue (IfThenElse cond' v2 v3) t2
389+ return $ TypedValue True (IfThenElse cond' v2 v3) t2
390−infer' (TypedValue val ty) = do
390+infer' (TypedValue checkType val ty) = do
391 moduleName <- substCurrentModule <$> ask
391 moduleName <- substCurrentModule <$> ask
392 kind <- liftCheck $ kindOf moduleName ty
392 kind <- liftCheck $ kindOf moduleName ty
393 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
393 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
394 ty' <- replaceAllTypeSynonyms ty
394 ty' <- replaceAllTypeSynonyms ty
395− val' <- check val ty'
395+ val' <- if checkType then check val ty' else return val
396− return $ TypedValue val' ty
396+ return $ TypedValue True val' ty
397infer' _ = error "Invalid argument to infer"
397infer' _ = error "Invalid argument to infer"
399inferProperty :: Type -> String -> Subst (Maybe Type)
399inferProperty :: Type -> String -> Subst (Maybe Type)
@@ -409,11 +409,11 @@ inferProperty (ForAll ident ty) prop = do
409inferProperty _ _ = return Nothing
409inferProperty _ _ = return Nothing
411inferUnary :: UnaryOperator -> Value -> Subst Value
411inferUnary :: UnaryOperator -> Value -> Subst Value
412−inferUnary op (TypedValue val valTy) =
412+inferUnary op (TypedValue _ val valTy) =
413 case fromMaybe (error "Invalid operator") $ lookup op unaryOps of
413 case fromMaybe (error "Invalid operator") $ lookup op unaryOps of
414 (valTy', resTy) -> do
414 (valTy', resTy) -> do
415 valTy' ~~ valTy
415 valTy' ~~ valTy
416− return $ TypedValue (Unary op val) resTy
416+ return $ TypedValue True (Unary op val) resTy
417inferUnary _ _ = error "Invalid arguments to inferUnary"
417inferUnary _ _ = error "Invalid arguments to inferUnary"
419checkUnary :: UnaryOperator -> Value -> Type -> Subst Value
419checkUnary :: UnaryOperator -> Value -> Type -> Subst Value
@@ -431,22 +431,22 @@ unaryOps = [ (Negate, (Number, Number))
433inferBinary :: BinaryOperator -> Value -> Value -> Subst Value
433inferBinary :: BinaryOperator -> Value -> Value -> Subst Value
434−inferBinary op left@(TypedValue _ leftTy) right@(TypedValue _ rightTy) | isEqualityTest op = do
434+inferBinary op left@(TypedValue _ _ leftTy) right@(TypedValue _ _ rightTy) | isEqualityTest op = do
435 leftTy ~~ rightTy
435 leftTy ~~ rightTy
436− return $ TypedValue (Binary op left right) Boolean
436+ return $ TypedValue True (Binary op left right) Boolean
437−inferBinary op left@(TypedValue _ leftTy) right@(TypedValue _ rightTy) =
437+inferBinary op left@(TypedValue _ _ leftTy) right@(TypedValue _ _ rightTy) =
438 case fromMaybe (error "Invalid operator") $ lookup op binaryOps of
438 case fromMaybe (error "Invalid operator") $ lookup op binaryOps of
439 (valTy, resTy) -> do
439 (valTy, resTy) -> do
440 leftTy ~~ valTy
440 leftTy ~~ valTy
441 rightTy ~~ valTy
441 rightTy ~~ valTy
442− return $ TypedValue (Binary op left right) resTy
442+ return $ TypedValue True (Binary op left right) resTy
443inferBinary _ _ _ = error "Invalid arguments to inferBinary"
443inferBinary _ _ _ = error "Invalid arguments to inferBinary"
445checkBinary :: BinaryOperator -> Value -> Value -> Type -> Subst Value
445checkBinary :: BinaryOperator -> Value -> Value -> Type -> Subst Value
446checkBinary op left right res | isEqualityTest op = do
446checkBinary op left right res | isEqualityTest op = do
447 res ~~ Boolean
447 res ~~ Boolean
448− left'@(TypedValue _ t1) <- infer left
448+ left'@(TypedValue _ _ t1) <- infer left
449− right'@(TypedValue _ t2) <- infer right
449+ right'@(TypedValue _ _ t2) <- infer right
451 return $ Binary op left' right'
451 return $ Binary op left' right'
452checkBinary op left right res =
452checkBinary op left right res =
@@ -564,10 +564,10 @@ assignVariable name = do
564checkStatement :: M.Map Ident Type -> Type -> Statement -> Subst (Bool, M.Map Ident Type, Statement)
564checkStatement :: M.Map Ident Type -> Type -> Statement -> Subst (Bool, M.Map Ident Type, Statement)
565checkStatement mass _ (VariableIntroduction name val) = do
565checkStatement mass _ (VariableIntroduction name val) = do
566 assignVariable name
566 assignVariable name
567− val'@(TypedValue _ t) <- infer val
567+ val'@(TypedValue _ _ t) <- infer val
568 return (False, M.insert name t mass, VariableIntroduction name val')
568 return (False, M.insert name t mass, VariableIntroduction name val')
569checkStatement mass _ (Assignment ident val) = do
569checkStatement mass _ (Assignment ident val) = do
570− val'@(TypedValue _ t) <- infer val
570+ val'@(TypedValue _ _ t) <- infer val
571 case M.lookup ident mass of
571 case M.lookup ident mass of
572 Nothing -> throwError $ "No local variable with name " ++ show ident
572 Nothing -> throwError $ "No local variable with name " ++ show ident
573 Just ty -> do t ~~ ty
573 Just ty -> do t ~~ ty
@@ -648,7 +648,7 @@ check' val (ConstrainedType constraints ty) = do
648 val' <- withTypeClassDictionaries (zipWith (\name (className, instanceTy) -> TypeClassDictionaryInScope name className instanceTy Nothing) dictNames (qualifyAllUnqualifiedNames moduleName env constraints)) $ check val ty
648 val' <- withTypeClassDictionaries (zipWith (\name (className, instanceTy) -> TypeClassDictionaryInScope name className instanceTy Nothing) dictNames (qualifyAllUnqualifiedNames moduleName env constraints)) $ check val ty
649 return $ Abs dictNames val'
649 return $ Abs dictNames val'
650check' val u@(TUnknown _) = do
650check' val u@(TUnknown _) = do
651− val'@(TypedValue _ ty) <- infer val
651+ val'@(TypedValue _ _ ty) <- infer val
652 -- Don't unify an unknown with an inferred polytype
652 -- Don't unify an unknown with an inferred polytype
653 ty' <- replaceAllVarsWithUnknowns ty
653 ty' <- replaceAllVarsWithUnknowns ty
@@ -669,7 +669,7 @@ check' (Abs args ret) (Function argTys retTy) = do
669 ret' <- bindLocalVariables moduleName (zip args argTys) $ check ret retTy
669 ret' <- bindLocalVariables moduleName (zip args argTys) $ check ret retTy
670 return $ Abs args ret'
670 return $ Abs args ret'
671check' (App f args) ret = do
671check' (App f args) ret = do
672− f'@(TypedValue _ ft) <- infer f
672+ f'@(TypedValue _ _ ft) <- infer f
673 app <- checkFunctionApplication f' ft args ret
673 app <- checkFunctionApplication f' ft args ret
674 return $ app
674 return $ app
675check' (Var var) ty = do
675check' (Var var) ty = do
@@ -678,16 +678,16 @@ check' (Var var) ty = do
678 repl <- replaceAllTypeSynonyms ty1
678 repl <- replaceAllTypeSynonyms ty1
679 repl `subsumes` ty
679 repl `subsumes` ty
680 return $ Var var
680 return $ Var var
681−check' (TypedValue val ty1) ty2 = do
681+check' (TypedValue checkType val ty1) ty2 = do
682 moduleName <- substCurrentModule <$> ask
682 moduleName <- substCurrentModule <$> ask
683 kind <- liftCheck $ kindOf moduleName ty1
683 kind <- liftCheck $ kindOf moduleName ty1
684 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
684 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
685 ty1 `subsumes` ty2
685 ty1 `subsumes` ty2
686− val' <- check val ty1
686+ val' <- if checkType then check val ty1 else return val
687− return $ TypedValue val' ty1
687+ return $ TypedValue True val' ty1
688check' (Case vals binders) ret = do
688check' (Case vals binders) ret = do
689 vals' <- mapM infer vals
689 vals' <- mapM infer vals
690− let ts = map (\(TypedValue _ t) -> t) vals'
690+ let ts = map (\(TypedValue _ _ t) -> t) vals'
691 binders' <- checkBinders ts ret binders
691 binders' <- checkBinders ts ret binders
692 return $ Case vals' binders'
692 return $ Case vals' binders'
693check' (IfThenElse cond th el) ty = do
693check' (IfThenElse cond th el) ty = do
@@ -740,7 +740,7 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
740 | otherwise = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have property " ++ p
740 | otherwise = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have property " ++ p
741 go ((p,_):_) [] REmpty = throwError $ "Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row
741 go ((p,_):_) [] REmpty = throwError $ "Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row
742 go ((p,v):ps') [] u@(TUnknown _) = do
742 go ((p,v):ps') [] u@(TUnknown _) = do
743− v'@(TypedValue _ ty) <- infer v
743+ v'@(TypedValue _ _ ty) <- infer v
744 rest <- fresh
744 rest <- fresh
745 u ~~ RCons p ty rest
745 u ~~ RCons p ty rest
746 ps'' <- go ps' [] rest
746 ps'' <- go ps' [] rest
@@ -748,7 +748,7 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
748 go ((p,v):ps') ts r =
748 go ((p,v):ps') ts r =
749 case lookup p ts of
749 case lookup p ts of
750 Nothing -> do
750 Nothing -> do
751− v'@(TypedValue _ ty) <- infer v
751+ v'@(TypedValue _ _ ty) <- infer v
752 rest <- fresh
752 rest <- fresh
753 r ~~ RCons p ty rest
753 r ~~ RCons p ty rest
754 ps'' <- go ps' ts rest
754 ps'' <- go ps' ts rest
@@ -777,8 +777,8 @@ checkFunctionApplication' fn (ForAll ident ty) args ret = do
777 replaced <- replaceVarWithUnknown ident ty
777 replaced <- replaceVarWithUnknown ident ty
778 checkFunctionApplication fn replaced args ret
778 checkFunctionApplication fn replaced args ret
779checkFunctionApplication' fn u@(TUnknown _) args ret = do
779checkFunctionApplication' fn u@(TUnknown _) args ret = do
780− args' <- mapM (\arg -> infer arg >>= \(TypedValue v t) -> TypedValue v <$> replaceAllVarsWithUnknowns t) args
780+ args' <- mapM (\arg -> infer arg >>= \(TypedValue _ v t) -> TypedValue True v <$> replaceAllVarsWithUnknowns t) args
781− let tys = map (\(TypedValue _ t) -> t) args'
781+ let tys = map (\(TypedValue _ _ t) -> t) args'
782 u ~~ Function tys ret
782 u ~~ Function tys ret
783 return $ App fn args'
783 return $ App fn args'
784checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) args ret = do
784checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) args ret = do