Simply-typed Curry-style (nominal) lambda-calculus with integers and zero-comparison Type inference, of the type and of the environment, aka conditional typechecking This code does not in general infer polymorphic bindings as this is akin to higher-order unification.
The benefit of the approach: we can handle _open_ terms. Some of them we type check, and some of them we reject. The rejection means the term cannot be typed in _any_ type environment.
One often hears a complaint against typing: one can evaluate terms we can't even type check. This code shows that we can type check terms we can't even evaluate.
We cannot evaluate open terms at all, but we can type check them, inferring both the type as well as the _requirement_ on the environments in which the term must be used.
- data Typ
- type TVarName = Int
- data Term
- type VarName = String
- type TEnv = [(VarName, Typ)]
- env0 :: TEnv
- lkup :: TEnv -> VarName -> Typ
- ext :: TEnv -> (VarName, Typ) -> TEnv
- unext :: TEnv -> VarName -> TEnv
- env_map :: (Typ -> Typ) -> TEnv -> TEnv
- env_fold_merge :: TEnv -> TEnv -> (Typ -> Typ -> seed -> Either err seed) -> seed -> Either err (TEnv, seed)
- data TVE = TVE Int (IntMap Typ)
- newtv :: TVE -> (Typ, TVE)
- tve0 :: TVE
- tvlkup :: TVE -> TVarName -> Maybe Typ
- tvext :: TVE -> (TVarName, Typ) -> TVE
- tvsub :: TVE -> Typ -> Typ
- tvchase :: TVE -> Typ -> Typ
- unify :: Typ -> Typ -> TVE -> Either String TVE
- unify' :: Typ -> Typ -> TVE -> Either String TVE
- unifyv :: TVarName -> Typ -> TVE -> Either String TVE
- occurs :: TVarName -> Typ -> TVE -> Bool
- merge_env :: TEnv -> TEnv -> TVE -> (TEnv, TVE)
- teval' :: Term -> TVE -> (Typ, TEnv, TVE)
- teval :: Term -> (Typ, TEnv)
Documentation
env_fold_merge :: TEnv -> TEnv -> (Typ -> Typ -> seed -> Either err seed) -> seed -> Either err (TEnv, seed)Source
Merge two environment, using the given function to resolve the conflicts, if any
Type Variable Environment: associating types with free
type variables
tvchase :: TVE -> Typ -> TypSource
shallow
substitution; check if tv is bound to anything substantial
unify :: Typ -> Typ -> TVE -> Either String TVESource
The unification. If unification failed, return the reason
unify' :: Typ -> Typ -> TVE -> Either String TVESource
If either t1 or t2 are type variables, they are definitely unbound