Extending Hindley-Milner to type mutable referencesType inference for imperative statements other than assignmentNested automatization of type inference of forall eliminationHow are imperative languages more different from each other than functional languages?Type inference for imperative statements other than assignmentOccurs check in type inferencePractical implementation of Hindley–Milner with typeclasses — matching vs most general unifierIs this behavior in a programming language inconsistent?Can type inference be classified in two groups: unification-based and control-flow-based?Decidability of parametric higher-order type unificationHigher-rank polymorphism over unboxed typesLanguage/type system closest to Haskell without general recursion

How do I keep an essay about "feeling flat" from feeling flat?

Curses work by shouting - How to avoid collateral damage?

What's the purpose of "true" in bash "if sudo true; then"

What defines a dissertation?

Personal Teleportation as a Weapon

Applicability of Single Responsibility Principle

Implement the Thanos sorting algorithm

Best way to store options for panels

Teaching indefinite integrals that require special-casing

Using parameter substitution on a Bash array

Was Spock the First Vulcan in Starfleet?

Modify casing of marked letters

Why is delta-v is the most useful quantity for planning space travel?

Minimal reference content

Why are on-board computers allowed to change controls without notifying the pilots?

What will be the benefits of Brexit?

What to do with wrong results in talks?

Modulo 2 binary long division in European notation

How can I get through very long and very dry, but also very useful technical documents when learning a new tool?

How does residential electricity work?

Can I Retrieve Email Addresses from BCC?

How do I rename a LINUX host without needing to reboot for the rename to take effect?

Mapping a list into a phase plot

Is there any reason not to eat food that's been dropped on the surface of the moon?



Extending Hindley-Milner to type mutable references


Type inference for imperative statements other than assignmentNested automatization of type inference of forall eliminationHow are imperative languages more different from each other than functional languages?Type inference for imperative statements other than assignmentOccurs check in type inferencePractical implementation of Hindley–Milner with typeclasses — matching vs most general unifierIs this behavior in a programming language inconsistent?Can type inference be classified in two groups: unification-based and control-flow-based?Decidability of parametric higher-order type unificationHigher-rank polymorphism over unboxed typesLanguage/type system closest to Haskell without general recursion













2












$begingroup$


I have been trying to implement a programming language from scratch, and have gotten reasonably far. It reads just like Python, other than the fact that let is used to declare a variable as opposed to a bare assignment.



However, I'm now trying to add mutability into the language, specifically in the syntactical form



let mut x = 1


where x is now a rebindable variable. This is effectively the same as



let x = ref 1 in ...


in ML, but my type-checker inserts the dereference operator (!) automatically. So something like ref is never directly used. Any instance of x has a ! applied to it. So, if you do



let mut x = 1
let y = x
x = 2


Then x is still rebindable, and has the value of 2, but y is immutable and has the value 1.



I am having great difficulty extending my implementation of Hindley-Milner 's unification to support mutable references. The main paper I was reading was Standard ML-NJ Weak Polymorphism and Imperative Constructs by John Mitchell, as I was hoping to get an inference algorithm that had similar behavior to OCaml's weak polymorphism implementation.



This paper is pretty good and explains most things well enough, but it lacks a formal description of the type inference algorithm for its language. Are there any good resources on extending Hindley-Milners unification algorithm, that is, not the type system, with mutable references. I know the two go hand in hand, but I'm just having a really hard time jumping from the type inference rules from the paper I'm using to extending my implementation. I'm wondering if there is at least a description of an algorithm that unifies types in a language that supports mutable references.



Lastly, I saw this question here asking something similar. The asker states "I only find solutions for a language with mutable references but without genuine imperative control structures", I would like to see those references! I completely understand how to extend my language to have imperative control structures once I get my mutable references working, but this is where I am stuck now.










share|cite|improve this question









New contributor




Enrico Borba is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$











  • $begingroup$
    I'm not sure I fully understand your question. Are you asking about how to do type inference when types of variables depend on whether they occur on the LHS or RHS of an assignment? And: based on what information does your type-checker insert dereference operators automatically?
    $endgroup$
    – Martin Berger
    Mar 20 at 10:50










  • $begingroup$
    BTW, there is a subtlety with automatic dereferencing on the RHS: assume you declare let mut x = 1 and then let mut y = x or let z = x. With auto-derefering, y will have type Ref Int and z will have type Int, but this is not always what you want. Sometimes you want y to have type Ref Ref Int, hence be an alias of x, or z be of type Ref int. How does your language handle this edge case?
    $endgroup$
    – Martin Berger
    Mar 20 at 11:48










  • $begingroup$
    I edited my question to clarify about the use of mutable bindings. let mut x = 1 means x has type Int, and can be used anywhere where an Int is accepted. Basically, if x was created with let mut, then anywhere an x appears it is actually treated as !x.
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:00















2












$begingroup$


I have been trying to implement a programming language from scratch, and have gotten reasonably far. It reads just like Python, other than the fact that let is used to declare a variable as opposed to a bare assignment.



However, I'm now trying to add mutability into the language, specifically in the syntactical form



let mut x = 1


where x is now a rebindable variable. This is effectively the same as



let x = ref 1 in ...


in ML, but my type-checker inserts the dereference operator (!) automatically. So something like ref is never directly used. Any instance of x has a ! applied to it. So, if you do



let mut x = 1
let y = x
x = 2


Then x is still rebindable, and has the value of 2, but y is immutable and has the value 1.



I am having great difficulty extending my implementation of Hindley-Milner 's unification to support mutable references. The main paper I was reading was Standard ML-NJ Weak Polymorphism and Imperative Constructs by John Mitchell, as I was hoping to get an inference algorithm that had similar behavior to OCaml's weak polymorphism implementation.



This paper is pretty good and explains most things well enough, but it lacks a formal description of the type inference algorithm for its language. Are there any good resources on extending Hindley-Milners unification algorithm, that is, not the type system, with mutable references. I know the two go hand in hand, but I'm just having a really hard time jumping from the type inference rules from the paper I'm using to extending my implementation. I'm wondering if there is at least a description of an algorithm that unifies types in a language that supports mutable references.



Lastly, I saw this question here asking something similar. The asker states "I only find solutions for a language with mutable references but without genuine imperative control structures", I would like to see those references! I completely understand how to extend my language to have imperative control structures once I get my mutable references working, but this is where I am stuck now.










share|cite|improve this question









New contributor




Enrico Borba is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$











  • $begingroup$
    I'm not sure I fully understand your question. Are you asking about how to do type inference when types of variables depend on whether they occur on the LHS or RHS of an assignment? And: based on what information does your type-checker insert dereference operators automatically?
    $endgroup$
    – Martin Berger
    Mar 20 at 10:50










  • $begingroup$
    BTW, there is a subtlety with automatic dereferencing on the RHS: assume you declare let mut x = 1 and then let mut y = x or let z = x. With auto-derefering, y will have type Ref Int and z will have type Int, but this is not always what you want. Sometimes you want y to have type Ref Ref Int, hence be an alias of x, or z be of type Ref int. How does your language handle this edge case?
    $endgroup$
    – Martin Berger
    Mar 20 at 11:48










  • $begingroup$
    I edited my question to clarify about the use of mutable bindings. let mut x = 1 means x has type Int, and can be used anywhere where an Int is accepted. Basically, if x was created with let mut, then anywhere an x appears it is actually treated as !x.
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:00













2












2








2





$begingroup$


I have been trying to implement a programming language from scratch, and have gotten reasonably far. It reads just like Python, other than the fact that let is used to declare a variable as opposed to a bare assignment.



However, I'm now trying to add mutability into the language, specifically in the syntactical form



let mut x = 1


where x is now a rebindable variable. This is effectively the same as



let x = ref 1 in ...


in ML, but my type-checker inserts the dereference operator (!) automatically. So something like ref is never directly used. Any instance of x has a ! applied to it. So, if you do



let mut x = 1
let y = x
x = 2


Then x is still rebindable, and has the value of 2, but y is immutable and has the value 1.



I am having great difficulty extending my implementation of Hindley-Milner 's unification to support mutable references. The main paper I was reading was Standard ML-NJ Weak Polymorphism and Imperative Constructs by John Mitchell, as I was hoping to get an inference algorithm that had similar behavior to OCaml's weak polymorphism implementation.



This paper is pretty good and explains most things well enough, but it lacks a formal description of the type inference algorithm for its language. Are there any good resources on extending Hindley-Milners unification algorithm, that is, not the type system, with mutable references. I know the two go hand in hand, but I'm just having a really hard time jumping from the type inference rules from the paper I'm using to extending my implementation. I'm wondering if there is at least a description of an algorithm that unifies types in a language that supports mutable references.



Lastly, I saw this question here asking something similar. The asker states "I only find solutions for a language with mutable references but without genuine imperative control structures", I would like to see those references! I completely understand how to extend my language to have imperative control structures once I get my mutable references working, but this is where I am stuck now.










share|cite|improve this question









New contributor




Enrico Borba is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$




I have been trying to implement a programming language from scratch, and have gotten reasonably far. It reads just like Python, other than the fact that let is used to declare a variable as opposed to a bare assignment.



However, I'm now trying to add mutability into the language, specifically in the syntactical form



let mut x = 1


where x is now a rebindable variable. This is effectively the same as



let x = ref 1 in ...


in ML, but my type-checker inserts the dereference operator (!) automatically. So something like ref is never directly used. Any instance of x has a ! applied to it. So, if you do



let mut x = 1
let y = x
x = 2


Then x is still rebindable, and has the value of 2, but y is immutable and has the value 1.



I am having great difficulty extending my implementation of Hindley-Milner 's unification to support mutable references. The main paper I was reading was Standard ML-NJ Weak Polymorphism and Imperative Constructs by John Mitchell, as I was hoping to get an inference algorithm that had similar behavior to OCaml's weak polymorphism implementation.



This paper is pretty good and explains most things well enough, but it lacks a formal description of the type inference algorithm for its language. Are there any good resources on extending Hindley-Milners unification algorithm, that is, not the type system, with mutable references. I know the two go hand in hand, but I'm just having a really hard time jumping from the type inference rules from the paper I'm using to extending my implementation. I'm wondering if there is at least a description of an algorithm that unifies types in a language that supports mutable references.



Lastly, I saw this question here asking something similar. The asker states "I only find solutions for a language with mutable references but without genuine imperative control structures", I would like to see those references! I completely understand how to extend my language to have imperative control structures once I get my mutable references working, but this is where I am stuck now.







reference-request pl.programming-languages type-theory type-inference imperative-programming






share|cite|improve this question









New contributor




Enrico Borba is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|cite|improve this question









New contributor




Enrico Borba is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|cite|improve this question




share|cite|improve this question








edited Mar 20 at 15:57







Enrico Borba













New contributor




Enrico Borba is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Mar 20 at 7:21









Enrico BorbaEnrico Borba

1134




1134




New contributor




Enrico Borba is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Enrico Borba is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Enrico Borba is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











  • $begingroup$
    I'm not sure I fully understand your question. Are you asking about how to do type inference when types of variables depend on whether they occur on the LHS or RHS of an assignment? And: based on what information does your type-checker insert dereference operators automatically?
    $endgroup$
    – Martin Berger
    Mar 20 at 10:50










  • $begingroup$
    BTW, there is a subtlety with automatic dereferencing on the RHS: assume you declare let mut x = 1 and then let mut y = x or let z = x. With auto-derefering, y will have type Ref Int and z will have type Int, but this is not always what you want. Sometimes you want y to have type Ref Ref Int, hence be an alias of x, or z be of type Ref int. How does your language handle this edge case?
    $endgroup$
    – Martin Berger
    Mar 20 at 11:48










  • $begingroup$
    I edited my question to clarify about the use of mutable bindings. let mut x = 1 means x has type Int, and can be used anywhere where an Int is accepted. Basically, if x was created with let mut, then anywhere an x appears it is actually treated as !x.
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:00
















  • $begingroup$
    I'm not sure I fully understand your question. Are you asking about how to do type inference when types of variables depend on whether they occur on the LHS or RHS of an assignment? And: based on what information does your type-checker insert dereference operators automatically?
    $endgroup$
    – Martin Berger
    Mar 20 at 10:50










  • $begingroup$
    BTW, there is a subtlety with automatic dereferencing on the RHS: assume you declare let mut x = 1 and then let mut y = x or let z = x. With auto-derefering, y will have type Ref Int and z will have type Int, but this is not always what you want. Sometimes you want y to have type Ref Ref Int, hence be an alias of x, or z be of type Ref int. How does your language handle this edge case?
    $endgroup$
    – Martin Berger
    Mar 20 at 11:48










  • $begingroup$
    I edited my question to clarify about the use of mutable bindings. let mut x = 1 means x has type Int, and can be used anywhere where an Int is accepted. Basically, if x was created with let mut, then anywhere an x appears it is actually treated as !x.
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:00















$begingroup$
I'm not sure I fully understand your question. Are you asking about how to do type inference when types of variables depend on whether they occur on the LHS or RHS of an assignment? And: based on what information does your type-checker insert dereference operators automatically?
$endgroup$
– Martin Berger
Mar 20 at 10:50




$begingroup$
I'm not sure I fully understand your question. Are you asking about how to do type inference when types of variables depend on whether they occur on the LHS or RHS of an assignment? And: based on what information does your type-checker insert dereference operators automatically?
$endgroup$
– Martin Berger
Mar 20 at 10:50












$begingroup$
BTW, there is a subtlety with automatic dereferencing on the RHS: assume you declare let mut x = 1 and then let mut y = x or let z = x. With auto-derefering, y will have type Ref Int and z will have type Int, but this is not always what you want. Sometimes you want y to have type Ref Ref Int, hence be an alias of x, or z be of type Ref int. How does your language handle this edge case?
$endgroup$
– Martin Berger
Mar 20 at 11:48




$begingroup$
BTW, there is a subtlety with automatic dereferencing on the RHS: assume you declare let mut x = 1 and then let mut y = x or let z = x. With auto-derefering, y will have type Ref Int and z will have type Int, but this is not always what you want. Sometimes you want y to have type Ref Ref Int, hence be an alias of x, or z be of type Ref int. How does your language handle this edge case?
$endgroup$
– Martin Berger
Mar 20 at 11:48












$begingroup$
I edited my question to clarify about the use of mutable bindings. let mut x = 1 means x has type Int, and can be used anywhere where an Int is accepted. Basically, if x was created with let mut, then anywhere an x appears it is actually treated as !x.
$endgroup$
– Enrico Borba
Mar 20 at 16:00




$begingroup$
I edited my question to clarify about the use of mutable bindings. let mut x = 1 means x has type Int, and can be used anywhere where an Int is accepted. Basically, if x was created with let mut, then anywhere an x appears it is actually treated as !x.
$endgroup$
– Enrico Borba
Mar 20 at 16:00










2 Answers
2






active

oldest

votes


















5












$begingroup$

To get behaviour similar to Ocaml, simply avoid generalizing the type of mutable variables.



With ordinary let-bindings, you generalize if you bind a value, and don't generalize otherwise. With mutable variable bindings, you never generalize.



The standard ML-like behaviour is then:



let xs = [] // xs : forall a. list a 

let as = 1 :: xs // as : list int -- instantiate a to int
let bs = true :: xs // bs : list bool -- instantiate a to bool


The mutable variable typing will go:



let mut xs = [] // xs : list ?a -- a is an unification variable

let as = 1 :: xs // as : list int AND ALSO
// xs : list int, since ?a gets resolved to int
let bs = true :: xs // TYPE ERROR, since xs : list int





share|cite|improve this answer









$endgroup$












  • $begingroup$
    This is probably what I should do. I'll try to find some resources on what exactly OCaml treats as a value. Then, I'll try to relax the value restriction using Jacques Garrigue's paper, Relaxing the Value Restriction. Thanks
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:01










  • $begingroup$
    Man I really feel goofy. I've been spending the past week trying to implement the type system described in the paper by John Mitchell that I mentioned in the question. OCaml's value restriction was much easier to implement. Took me about 1 hour to implement lack of generalization for non-expansive values, and to get mutability working. Thank you so much for this suggestion.
    $endgroup$
    – Enrico Borba
    Mar 20 at 19:29










  • $begingroup$
    According to legend, this is basically what the whole research community felt when Andrew Wright came up with the value restriction.
    $endgroup$
    – Neel Krishnaswami
    Mar 21 at 13:21


















4












$begingroup$

As Martin Berger points out in his comment, it is not actually entirely obvious what the semantics of your language is supposed to be and what "automatically inserting !" means. Consider the following bindings:



let mut x = 1
let y = x // x or !x ?
let mut z = x // x or !x ?
let f a = (y := a) // legal?
let g a = (z := a; x) // will this modify x?
let h r = (r := 4) // is this possible?


Are these all legal in your language? For those that are, what are their types?



FWIW, in ML, all of the above is allowed with ! inserted in the right places (and mut replaced with ref). The only way I can imagine this working in a language with second-class references but H/M typing is such that y is immutable, z is a separate reference from x, f hence is ill-typed, g does not mutate x, and h is impossible to write.



Once you have figured out the answers to this, i.e., the actual typing rules for your language, inference should be straightforward, following Neel's hint. You would treat mutability as an attribute separate from types. Then unification is not affected at all, only generalisation. But as the last example shows, this language is less expressive than ML.






share|cite|improve this answer











$endgroup$












  • $begingroup$
    I edited my question to clarify about the exact semantics of mutable bindings. Your guess was correct about how the semantics would work. I'll try to implement OCaml's standard value restriction then. Thanks!
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:03










  • $begingroup$
    Note: the ambiguities above only exist if you think in terms of an encoding of his language using ML-stlye ref-cells. If you look at it from an imperative programming language with mutable variables there is no ambiguity: x is not a ref-cell but a mutable variable.
    $endgroup$
    – Stefan
    Mar 20 at 17:05











  • $begingroup$
    @Stefan, yes, but as I mention, that requires tracking mutability separately from types, otherwise type inference will be ambiguous. And that in turn requires introducing first-class references (a.k.a. pointers) as a separate concept that retains explicit dereferencing, because this strategy does not scale to the first-class case.
    $endgroup$
    – Andreas Rossberg
    Mar 20 at 20:35










Your Answer





StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
);
);
, "mathjax-editing");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "114"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
noCode: true, onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);






Enrico Borba is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcstheory.stackexchange.com%2fquestions%2f42554%2fextending-hindley-milner-to-type-mutable-references%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









5












$begingroup$

To get behaviour similar to Ocaml, simply avoid generalizing the type of mutable variables.



With ordinary let-bindings, you generalize if you bind a value, and don't generalize otherwise. With mutable variable bindings, you never generalize.



The standard ML-like behaviour is then:



let xs = [] // xs : forall a. list a 

let as = 1 :: xs // as : list int -- instantiate a to int
let bs = true :: xs // bs : list bool -- instantiate a to bool


The mutable variable typing will go:



let mut xs = [] // xs : list ?a -- a is an unification variable

let as = 1 :: xs // as : list int AND ALSO
// xs : list int, since ?a gets resolved to int
let bs = true :: xs // TYPE ERROR, since xs : list int





share|cite|improve this answer









$endgroup$












  • $begingroup$
    This is probably what I should do. I'll try to find some resources on what exactly OCaml treats as a value. Then, I'll try to relax the value restriction using Jacques Garrigue's paper, Relaxing the Value Restriction. Thanks
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:01










  • $begingroup$
    Man I really feel goofy. I've been spending the past week trying to implement the type system described in the paper by John Mitchell that I mentioned in the question. OCaml's value restriction was much easier to implement. Took me about 1 hour to implement lack of generalization for non-expansive values, and to get mutability working. Thank you so much for this suggestion.
    $endgroup$
    – Enrico Borba
    Mar 20 at 19:29










  • $begingroup$
    According to legend, this is basically what the whole research community felt when Andrew Wright came up with the value restriction.
    $endgroup$
    – Neel Krishnaswami
    Mar 21 at 13:21















5












$begingroup$

To get behaviour similar to Ocaml, simply avoid generalizing the type of mutable variables.



With ordinary let-bindings, you generalize if you bind a value, and don't generalize otherwise. With mutable variable bindings, you never generalize.



The standard ML-like behaviour is then:



let xs = [] // xs : forall a. list a 

let as = 1 :: xs // as : list int -- instantiate a to int
let bs = true :: xs // bs : list bool -- instantiate a to bool


The mutable variable typing will go:



let mut xs = [] // xs : list ?a -- a is an unification variable

let as = 1 :: xs // as : list int AND ALSO
// xs : list int, since ?a gets resolved to int
let bs = true :: xs // TYPE ERROR, since xs : list int





share|cite|improve this answer









$endgroup$












  • $begingroup$
    This is probably what I should do. I'll try to find some resources on what exactly OCaml treats as a value. Then, I'll try to relax the value restriction using Jacques Garrigue's paper, Relaxing the Value Restriction. Thanks
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:01










  • $begingroup$
    Man I really feel goofy. I've been spending the past week trying to implement the type system described in the paper by John Mitchell that I mentioned in the question. OCaml's value restriction was much easier to implement. Took me about 1 hour to implement lack of generalization for non-expansive values, and to get mutability working. Thank you so much for this suggestion.
    $endgroup$
    – Enrico Borba
    Mar 20 at 19:29










  • $begingroup$
    According to legend, this is basically what the whole research community felt when Andrew Wright came up with the value restriction.
    $endgroup$
    – Neel Krishnaswami
    Mar 21 at 13:21













5












5








5





$begingroup$

To get behaviour similar to Ocaml, simply avoid generalizing the type of mutable variables.



With ordinary let-bindings, you generalize if you bind a value, and don't generalize otherwise. With mutable variable bindings, you never generalize.



The standard ML-like behaviour is then:



let xs = [] // xs : forall a. list a 

let as = 1 :: xs // as : list int -- instantiate a to int
let bs = true :: xs // bs : list bool -- instantiate a to bool


The mutable variable typing will go:



let mut xs = [] // xs : list ?a -- a is an unification variable

let as = 1 :: xs // as : list int AND ALSO
// xs : list int, since ?a gets resolved to int
let bs = true :: xs // TYPE ERROR, since xs : list int





share|cite|improve this answer









$endgroup$



To get behaviour similar to Ocaml, simply avoid generalizing the type of mutable variables.



With ordinary let-bindings, you generalize if you bind a value, and don't generalize otherwise. With mutable variable bindings, you never generalize.



The standard ML-like behaviour is then:



let xs = [] // xs : forall a. list a 

let as = 1 :: xs // as : list int -- instantiate a to int
let bs = true :: xs // bs : list bool -- instantiate a to bool


The mutable variable typing will go:



let mut xs = [] // xs : list ?a -- a is an unification variable

let as = 1 :: xs // as : list int AND ALSO
// xs : list int, since ?a gets resolved to int
let bs = true :: xs // TYPE ERROR, since xs : list int






share|cite|improve this answer












share|cite|improve this answer



share|cite|improve this answer










answered Mar 20 at 10:13









Neel KrishnaswamiNeel Krishnaswami

26.8k77151




26.8k77151











  • $begingroup$
    This is probably what I should do. I'll try to find some resources on what exactly OCaml treats as a value. Then, I'll try to relax the value restriction using Jacques Garrigue's paper, Relaxing the Value Restriction. Thanks
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:01










  • $begingroup$
    Man I really feel goofy. I've been spending the past week trying to implement the type system described in the paper by John Mitchell that I mentioned in the question. OCaml's value restriction was much easier to implement. Took me about 1 hour to implement lack of generalization for non-expansive values, and to get mutability working. Thank you so much for this suggestion.
    $endgroup$
    – Enrico Borba
    Mar 20 at 19:29










  • $begingroup$
    According to legend, this is basically what the whole research community felt when Andrew Wright came up with the value restriction.
    $endgroup$
    – Neel Krishnaswami
    Mar 21 at 13:21
















  • $begingroup$
    This is probably what I should do. I'll try to find some resources on what exactly OCaml treats as a value. Then, I'll try to relax the value restriction using Jacques Garrigue's paper, Relaxing the Value Restriction. Thanks
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:01










  • $begingroup$
    Man I really feel goofy. I've been spending the past week trying to implement the type system described in the paper by John Mitchell that I mentioned in the question. OCaml's value restriction was much easier to implement. Took me about 1 hour to implement lack of generalization for non-expansive values, and to get mutability working. Thank you so much for this suggestion.
    $endgroup$
    – Enrico Borba
    Mar 20 at 19:29










  • $begingroup$
    According to legend, this is basically what the whole research community felt when Andrew Wright came up with the value restriction.
    $endgroup$
    – Neel Krishnaswami
    Mar 21 at 13:21















$begingroup$
This is probably what I should do. I'll try to find some resources on what exactly OCaml treats as a value. Then, I'll try to relax the value restriction using Jacques Garrigue's paper, Relaxing the Value Restriction. Thanks
$endgroup$
– Enrico Borba
Mar 20 at 16:01




$begingroup$
This is probably what I should do. I'll try to find some resources on what exactly OCaml treats as a value. Then, I'll try to relax the value restriction using Jacques Garrigue's paper, Relaxing the Value Restriction. Thanks
$endgroup$
– Enrico Borba
Mar 20 at 16:01












$begingroup$
Man I really feel goofy. I've been spending the past week trying to implement the type system described in the paper by John Mitchell that I mentioned in the question. OCaml's value restriction was much easier to implement. Took me about 1 hour to implement lack of generalization for non-expansive values, and to get mutability working. Thank you so much for this suggestion.
$endgroup$
– Enrico Borba
Mar 20 at 19:29




$begingroup$
Man I really feel goofy. I've been spending the past week trying to implement the type system described in the paper by John Mitchell that I mentioned in the question. OCaml's value restriction was much easier to implement. Took me about 1 hour to implement lack of generalization for non-expansive values, and to get mutability working. Thank you so much for this suggestion.
$endgroup$
– Enrico Borba
Mar 20 at 19:29












$begingroup$
According to legend, this is basically what the whole research community felt when Andrew Wright came up with the value restriction.
$endgroup$
– Neel Krishnaswami
Mar 21 at 13:21




$begingroup$
According to legend, this is basically what the whole research community felt when Andrew Wright came up with the value restriction.
$endgroup$
– Neel Krishnaswami
Mar 21 at 13:21











4












$begingroup$

As Martin Berger points out in his comment, it is not actually entirely obvious what the semantics of your language is supposed to be and what "automatically inserting !" means. Consider the following bindings:



let mut x = 1
let y = x // x or !x ?
let mut z = x // x or !x ?
let f a = (y := a) // legal?
let g a = (z := a; x) // will this modify x?
let h r = (r := 4) // is this possible?


Are these all legal in your language? For those that are, what are their types?



FWIW, in ML, all of the above is allowed with ! inserted in the right places (and mut replaced with ref). The only way I can imagine this working in a language with second-class references but H/M typing is such that y is immutable, z is a separate reference from x, f hence is ill-typed, g does not mutate x, and h is impossible to write.



Once you have figured out the answers to this, i.e., the actual typing rules for your language, inference should be straightforward, following Neel's hint. You would treat mutability as an attribute separate from types. Then unification is not affected at all, only generalisation. But as the last example shows, this language is less expressive than ML.






share|cite|improve this answer











$endgroup$












  • $begingroup$
    I edited my question to clarify about the exact semantics of mutable bindings. Your guess was correct about how the semantics would work. I'll try to implement OCaml's standard value restriction then. Thanks!
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:03










  • $begingroup$
    Note: the ambiguities above only exist if you think in terms of an encoding of his language using ML-stlye ref-cells. If you look at it from an imperative programming language with mutable variables there is no ambiguity: x is not a ref-cell but a mutable variable.
    $endgroup$
    – Stefan
    Mar 20 at 17:05











  • $begingroup$
    @Stefan, yes, but as I mention, that requires tracking mutability separately from types, otherwise type inference will be ambiguous. And that in turn requires introducing first-class references (a.k.a. pointers) as a separate concept that retains explicit dereferencing, because this strategy does not scale to the first-class case.
    $endgroup$
    – Andreas Rossberg
    Mar 20 at 20:35















4












$begingroup$

As Martin Berger points out in his comment, it is not actually entirely obvious what the semantics of your language is supposed to be and what "automatically inserting !" means. Consider the following bindings:



let mut x = 1
let y = x // x or !x ?
let mut z = x // x or !x ?
let f a = (y := a) // legal?
let g a = (z := a; x) // will this modify x?
let h r = (r := 4) // is this possible?


Are these all legal in your language? For those that are, what are their types?



FWIW, in ML, all of the above is allowed with ! inserted in the right places (and mut replaced with ref). The only way I can imagine this working in a language with second-class references but H/M typing is such that y is immutable, z is a separate reference from x, f hence is ill-typed, g does not mutate x, and h is impossible to write.



Once you have figured out the answers to this, i.e., the actual typing rules for your language, inference should be straightforward, following Neel's hint. You would treat mutability as an attribute separate from types. Then unification is not affected at all, only generalisation. But as the last example shows, this language is less expressive than ML.






share|cite|improve this answer











$endgroup$












  • $begingroup$
    I edited my question to clarify about the exact semantics of mutable bindings. Your guess was correct about how the semantics would work. I'll try to implement OCaml's standard value restriction then. Thanks!
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:03










  • $begingroup$
    Note: the ambiguities above only exist if you think in terms of an encoding of his language using ML-stlye ref-cells. If you look at it from an imperative programming language with mutable variables there is no ambiguity: x is not a ref-cell but a mutable variable.
    $endgroup$
    – Stefan
    Mar 20 at 17:05











  • $begingroup$
    @Stefan, yes, but as I mention, that requires tracking mutability separately from types, otherwise type inference will be ambiguous. And that in turn requires introducing first-class references (a.k.a. pointers) as a separate concept that retains explicit dereferencing, because this strategy does not scale to the first-class case.
    $endgroup$
    – Andreas Rossberg
    Mar 20 at 20:35













4












4








4





$begingroup$

As Martin Berger points out in his comment, it is not actually entirely obvious what the semantics of your language is supposed to be and what "automatically inserting !" means. Consider the following bindings:



let mut x = 1
let y = x // x or !x ?
let mut z = x // x or !x ?
let f a = (y := a) // legal?
let g a = (z := a; x) // will this modify x?
let h r = (r := 4) // is this possible?


Are these all legal in your language? For those that are, what are their types?



FWIW, in ML, all of the above is allowed with ! inserted in the right places (and mut replaced with ref). The only way I can imagine this working in a language with second-class references but H/M typing is such that y is immutable, z is a separate reference from x, f hence is ill-typed, g does not mutate x, and h is impossible to write.



Once you have figured out the answers to this, i.e., the actual typing rules for your language, inference should be straightforward, following Neel's hint. You would treat mutability as an attribute separate from types. Then unification is not affected at all, only generalisation. But as the last example shows, this language is less expressive than ML.






share|cite|improve this answer











$endgroup$



As Martin Berger points out in his comment, it is not actually entirely obvious what the semantics of your language is supposed to be and what "automatically inserting !" means. Consider the following bindings:



let mut x = 1
let y = x // x or !x ?
let mut z = x // x or !x ?
let f a = (y := a) // legal?
let g a = (z := a; x) // will this modify x?
let h r = (r := 4) // is this possible?


Are these all legal in your language? For those that are, what are their types?



FWIW, in ML, all of the above is allowed with ! inserted in the right places (and mut replaced with ref). The only way I can imagine this working in a language with second-class references but H/M typing is such that y is immutable, z is a separate reference from x, f hence is ill-typed, g does not mutate x, and h is impossible to write.



Once you have figured out the answers to this, i.e., the actual typing rules for your language, inference should be straightforward, following Neel's hint. You would treat mutability as an attribute separate from types. Then unification is not affected at all, only generalisation. But as the last example shows, this language is less expressive than ML.







share|cite|improve this answer














share|cite|improve this answer



share|cite|improve this answer








edited Mar 20 at 12:40

























answered Mar 20 at 12:30









Andreas RossbergAndreas Rossberg

1,111911




1,111911











  • $begingroup$
    I edited my question to clarify about the exact semantics of mutable bindings. Your guess was correct about how the semantics would work. I'll try to implement OCaml's standard value restriction then. Thanks!
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:03










  • $begingroup$
    Note: the ambiguities above only exist if you think in terms of an encoding of his language using ML-stlye ref-cells. If you look at it from an imperative programming language with mutable variables there is no ambiguity: x is not a ref-cell but a mutable variable.
    $endgroup$
    – Stefan
    Mar 20 at 17:05











  • $begingroup$
    @Stefan, yes, but as I mention, that requires tracking mutability separately from types, otherwise type inference will be ambiguous. And that in turn requires introducing first-class references (a.k.a. pointers) as a separate concept that retains explicit dereferencing, because this strategy does not scale to the first-class case.
    $endgroup$
    – Andreas Rossberg
    Mar 20 at 20:35
















  • $begingroup$
    I edited my question to clarify about the exact semantics of mutable bindings. Your guess was correct about how the semantics would work. I'll try to implement OCaml's standard value restriction then. Thanks!
    $endgroup$
    – Enrico Borba
    Mar 20 at 16:03










  • $begingroup$
    Note: the ambiguities above only exist if you think in terms of an encoding of his language using ML-stlye ref-cells. If you look at it from an imperative programming language with mutable variables there is no ambiguity: x is not a ref-cell but a mutable variable.
    $endgroup$
    – Stefan
    Mar 20 at 17:05











  • $begingroup$
    @Stefan, yes, but as I mention, that requires tracking mutability separately from types, otherwise type inference will be ambiguous. And that in turn requires introducing first-class references (a.k.a. pointers) as a separate concept that retains explicit dereferencing, because this strategy does not scale to the first-class case.
    $endgroup$
    – Andreas Rossberg
    Mar 20 at 20:35















$begingroup$
I edited my question to clarify about the exact semantics of mutable bindings. Your guess was correct about how the semantics would work. I'll try to implement OCaml's standard value restriction then. Thanks!
$endgroup$
– Enrico Borba
Mar 20 at 16:03




$begingroup$
I edited my question to clarify about the exact semantics of mutable bindings. Your guess was correct about how the semantics would work. I'll try to implement OCaml's standard value restriction then. Thanks!
$endgroup$
– Enrico Borba
Mar 20 at 16:03












$begingroup$
Note: the ambiguities above only exist if you think in terms of an encoding of his language using ML-stlye ref-cells. If you look at it from an imperative programming language with mutable variables there is no ambiguity: x is not a ref-cell but a mutable variable.
$endgroup$
– Stefan
Mar 20 at 17:05





$begingroup$
Note: the ambiguities above only exist if you think in terms of an encoding of his language using ML-stlye ref-cells. If you look at it from an imperative programming language with mutable variables there is no ambiguity: x is not a ref-cell but a mutable variable.
$endgroup$
– Stefan
Mar 20 at 17:05













$begingroup$
@Stefan, yes, but as I mention, that requires tracking mutability separately from types, otherwise type inference will be ambiguous. And that in turn requires introducing first-class references (a.k.a. pointers) as a separate concept that retains explicit dereferencing, because this strategy does not scale to the first-class case.
$endgroup$
– Andreas Rossberg
Mar 20 at 20:35




$begingroup$
@Stefan, yes, but as I mention, that requires tracking mutability separately from types, otherwise type inference will be ambiguous. And that in turn requires introducing first-class references (a.k.a. pointers) as a separate concept that retains explicit dereferencing, because this strategy does not scale to the first-class case.
$endgroup$
– Andreas Rossberg
Mar 20 at 20:35










Enrico Borba is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded


















Enrico Borba is a new contributor. Be nice, and check out our Code of Conduct.












Enrico Borba is a new contributor. Be nice, and check out our Code of Conduct.











Enrico Borba is a new contributor. Be nice, and check out our Code of Conduct.














Thanks for contributing an answer to Theoretical Computer Science Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcstheory.stackexchange.com%2fquestions%2f42554%2fextending-hindley-milner-to-type-mutable-references%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Adding axes to figuresAdding axes labels to LaTeX figuresLaTeX equivalent of ConTeXt buffersRotate a node but not its content: the case of the ellipse decorationHow to define the default vertical distance between nodes?TikZ scaling graphic and adjust node position and keep font sizeNumerical conditional within tikz keys?adding axes to shapesAlign axes across subfiguresAdding figures with a certain orderLine up nested tikz enviroments or how to get rid of themAdding axes labels to LaTeX figures

Tähtien Talli Jäsenet | Lähteet | NavigointivalikkoSuomen Hippos – Tähtien Talli

Do these cracks on my tires look bad? The Next CEO of Stack OverflowDry rot tire should I replace?Having to replace tiresFishtailed so easily? Bad tires? ABS?Filling the tires with something other than air, to avoid puncture hassles?Used Michelin tires safe to install?Do these tyre cracks necessitate replacement?Rumbling noise: tires or mechanicalIs it possible to fix noisy feathered tires?Are bad winter tires still better than summer tires in winter?Torque converter failure - Related to replacing only 2 tires?Why use snow tires on all 4 wheels on 2-wheel-drive cars?