type-equations
#63
Open
Olivier
wants to merge 15 commits from type-equations
into type-equations-master
pull from: type-equations
merge into: Olivier:type-equations-master
Olivier:equality-constraint-graph
Olivier:introduce-rigid
Olivier:equality-constraint-env-immutable
Olivier:upstream
Olivier:equality-constraint-2
Olivier:issue-64
Olivier:issue-58
Olivier:equality-constraint
Olivier:master
Olivier:type-equations-master
Olivier:n-ary-fun-printing
Olivier:abstract
Olivier:rigid-variable-fix
Olivier:rigid-variable-rebase
Olivier:letrn
Olivier:gadt-language
Olivier:multi-eq
Olivier:error-message-rebase
Olivier:rigid-rebase
Olivier:error-message
Olivier:clearer-test-output
Olivier:ranges
Olivier:minor-fixes
Olivier:test-files
Olivier:alcotest
Olivier:abbrev_refactoring
Olivier:rigid-variable
Olivier:test-framework
Olivier:qcheck
Olivier:printer
Olivier:improve-ast
Olivier:parser
Olivier:last_push
Olivier:frozen-infer
Olivier:f-datatypes
Olivier:f-datatypes-wip
Olivier:match-upstream
Olivier:variants-upstream
Olivier:pretty-printer-upstream
Olivier:new-f-constructs-upstream
Olivier:frozen-solver2
Olivier:solver2
Olivier:match2
Olivier:frozen-solver
Olivier:frozen
Olivier:match
Olivier:variants
Olivier:debug
Olivier:new-api
Olivier:pretty-printer
Olivier:co_cps
Olivier:new-f-constructs
Olivier:separate-test
Olivier:type-environment
Reviewers
Request review
No reviewers
Labels
Apply labels
Clear labels
No items
No Label
Milestone
Set milestone
Clear milestone
No items
No Milestone
Assignees
Assign users
Clear assignees
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.
No due date set.
Dependencies
No dependencies set.
Reference: Olivier/inferno-experimental#63
Reference in new issue
There is no content yet.
Delete Branch 'type-equations'
Deleting a branch is permanent. It CANNOT be undone. Continue?
No
Yes
we must be able to display them as part of a type error message. *)
we must be able to display them as part of a type error message.
We use a restricted version of this system where a recursive cycle cannot
go through a universal quantifier. *)
Sauter une ligne avant, que ça fasse un paragraphe indépendant
"of this system" n'est pas ultra clair pour moi
Mentionner que c'est pour simplifier l'implémentation qu'on a mis cette restriction ?
Donner quelques exemples de types acceptés et rejetés:
forall a. mu t. a -> t
est accepté,mu t . forall a . (a -> t)
est rejeté. Qu'en est-il demu t . (forall a . a) -> t
? D'après ton explication ça devrait être accepté, mais je soupçonne que le code le rejette, il y a une incohérence ici.[Use] is a construct that "opens" a type equality. That is, it allows to
reason in a context a context where two types are assumed to be equals.
It is supposed to be used with a [Refl] as a left-hand side :
Euh, non ? Les cas intéressants sont ceux où le terme de type
TyEq(ty1, ty2)
n'est pas unRefl
mais un paramètre venant de l'extérieur / d'une structure de donnée.use (Refl ty) in t
est toujours équivalent àt
, puisqu'on introduit seulement l'égalité trivialety = ty
dans le contexte.str "The variable %s is unbound." x
| UnboundTypeVariable x ->
str "Scope error." ++
str "The variable %d is unbound." x
The type variable
[store] and [tyvars] *)
type consistency =
| Consistent of store * tyvars
| Inconsistent
Le nommage ici est bizarre: pourquoi une information de cohérence (
consistency
) contient-elle un store ?Contre-proposition:
(* This function assumes that no occurence of forall quantification
appear under a mu-type. *)
(* This function assumes no universal quantification inside a μ-type.
Pourquoi ? Parce qu'on ne sait pas tester l'équivalence entre types simplement dans ce cas.
- decompose an equality assumption
- perform an equality check
Since these two operations can be break down into similar parts, we
factorize the code, by passing a [mode] argument to the functions. *)
Je pense qu'on pourrait reformuler cette partie ensemble à notre prochaine discussion.
let (--) ty1 ty2 env : unit =
if not (equal Check env ty1 ty2) then
(* Re-package the type equality test as a type equality check. *)
let equal env ty1 ty2 : unit =
check_equal
?enforce_equal
? Pour moi une fonctionequal
renvoie unbool
.typeof { env with uf_state = Inconsistent } u
| ty ->
raise (TypeError (NotAnEqual ty))
end
Cette logique serait plus claire avec une fonction auxiliare
(j'utilise le nom
equation_env
que j'ai proposé plutôt queconsistency
actuellement, mais c'est la même chose.)let check
(env : F.nominal_datatype_env) (t : F.nominal_term)
(on_error : FTypeChecker.type_error -> unit)
(on_ok : unit -> unit)
En fait, est-ce que le code ne serait pas plus simple et plus clair si on changeait cette fonction pour renvoyer un
(debruijn_type, type_error) result
? Ou éventuellement(unit, type_error) result
si on sait qu'on n'utilise jamais le type calculé.(* Types mixing ∀ and μ are difficult to compare in general. To simplify
equality checking, we do not permit recursive cycles through universal
quantifiers, that is, we don't allow ∀ under μ.
"we do not permit recursive cycles through universal
quantifiers" and "we don't allow ∀ under μ" (do not) ne sont pas équivalents. La première version accepte le troisième exemple, la deuxième (qu'on implémente) le rejette.
... (* here ty1 and ty2 are assumed to be equal *)
Doing this might introduce inconsistent assumptions about types (this can
occur for example inside a pattern matching). That is why we introduce
donner l'exemple
int = bool
?Doing this might introduce inconsistent assumptions about types (this can
occur for example inside a pattern matching). That is why we introduce
a construct [Absurd], that can be used as a placeholder in pieces of code
where it happens and that are thus unreachable. *)
"where it happens" => "with inconsistent equations in the environment"
str "Type error." ++
str "The context is not absurd"
str "The typing context was expected to be inconsistent but is not." ++
str "This means that two types were assumed to be different but are not."
The type equations in the typing environment are not contradictory.
(* Is set to false when an inconsistent equation is introduced in the
environment. It is useful while typechecking pattern-matching. *)
consistent: bool;
(* We keep trace of wheter or not the typing equations is consistent *)
whether
store = UF.new_store();
tyvars = [];
consistent = true;
equations_env = Equations { store = UF.new_store() ; tyvars = [] };
"equations" here would work as well (
env.equations
), butequations_env
is okay.(* This function assumes no universal quantification inside a μ-type, because
it would be difficult to check type equality otherwise. That is why we need
a boolean [inside_mu] during the traversal of the type to remember wether
or not we are under a μ-quantification *)
The boolean [inside_mu] tracks whether we are already under a μ quantifier.
- decompose an equality assumption
- perform an equality check
Since these two operations can be break down into similar parts, we
factorize the code, by passing a [mode] argument to the functions. *)
We need two operations on equalities between types:
Both operations can be described as first decomposing a given equality "ty1 = ty2"
into "simple equalities" between a rigid variable and a type. In fact, the union-find data structure
that we use to represent an environment of equations store exactly those simple equlities.
Then:
The decomposition process does not produce simple equalities if the provided equality is absurd ("intint = intbool"). Then:
The functions below implement a unification procedure that implements both these operations, depending on a [mode] parameter:
(* Re-package the type equality test as a type equality check. *)
(* Re-package the type equality assumption as a type consistency check. *)
let consistent env ty1 ty2 : bool =
unify_types Input env ty1 ty2
Je propose de ne pas renvoyer un booléen mais un nouvel environment -- en fait ça renvient à inliner ce code dans
add_equation
.| Equations { store ; tyvars } ->
let store_copy = UF.copy store in
let equations_env = Equations { store = store_copy; tyvars } in
let env = { env with equations_env } in
on pourrait avoir un fonction
copy_env : env -> env
84491c2846
toa6b17c8d94
4 months agoa6b17c8d94
to934fb82b15
4 months ago