Is it possible to make Mutable Types support subtype? #1129
Replies: 4 comments 13 replies
-
This is a possible language design -- it's roughly how the array type in Java works. When you create an array in Java, it records the type it's supposed to have, and if you try to assign something wrong to it then there's a runtime error. So we could have a design where mutable pairs recorded the types of their two fields when they were created, and did runtime checks for those types on assignment. Then we would have covariant subtyping on mutable pairs. Unfortunately, this is a very different design than what Racket has today, so it would make it impossible for mpairs in Typed Racket to be the same as mpairs in Racket. That's a reasonable choice for a language, but Typed Racket aims to be highly-compatibly with Racket, so it won't work for Typed Racket. I'm going to move this to a "discussion" because that seems like a better place for discussing possible options for programs like this. |
Beta Was this translation helpful? Give feedback.
-
If every type-argument in a mutable type constructor were replaced with a pair of types with opposite variance, we could get something. I'll use b- <: a- and a+ <: b+
------------------------------
(Boxof a- a+) <: (Boxof b- b+) In other words in The > (contract-stronger? (box/c exact-integer? exact-integer?)
(box/c exact-integer? any/c))
#t
> (contract-stronger? (box/c exact-integer? exact-integer?)
(box/c any/c any/c))
#f For the example above with (MPairof (Natural, Natural) ((MListof (Natural, Natural)), Null)) <: (MListof (Natural, Natural)) This would also allow a more expressive type for (define-type (ReadOnlyMListof t)
(U Null (MPairof (Nothing, t) (Nothing, (ReadOnlyMListof t)))))
(: mlength (-> (ReadOnlyMListof Natural) Natural)) And then with that more expressive type the new (MPairof (Natural, Natural) (Null, Null)) <: (MPairof (Nothing, Natural) (Nothing, (ReadOnlyMListof Natural)))
--------------------------------------------------------------------------------------------------------------
(MPairof (Natural, Natural) (Null, Null)) <: (ReadOnlyMListof Natural) |
Beta Was this translation helpful? Give feedback.
-
In general, to look for more work on this topic, searching for "declaration site variance" vs "use-site variance" is the way to find papers, eg: https://dl.acm.org/doi/abs/10.1145/2489837.2489842 |
Beta Was this translation helpful? Give feedback.
-
It seems that supporting write types is more difficult than contracts: https://racket.discourse.group/t/a-new-way-to-type-mutable-data-structures-with-opposite-variance-in-typed-racket/1846/7?u=noahstorym . |
Beta Was this translation helpful? Give feedback.
-
I tried to write mlength for mlist, but it can't work for
(MPairof Natural Null)
type:I can understand it:
(MPairof Natural Null)
is not subtype of(MListof Natural)
because we can't run
(set-mcdr! mls (ann (mcons 8 '()) (MListof Natural)))
.But it's legal for mlength to run
(set-mcdr! m (ann (mcons 8 '()) (MListof Natural)))
in its body when mls bound to m, which cause conflict.
I wonder if it's possible to make Mutable Types support subtype, and when TR
found conflict, just throw an exception?
(I haven't studied type theory, I just wonder if it's feasible?)
for example:
when apply mls to change-1st!, it will record mls's type and value.
If mls's type is changed, then TR throws an exception.
(typecheck happens when the Mutable Type's assign operator was applied if the keyword is #:immediately,
or it happens when the calculation is finished if the keyword is #:end,
or it doesn't happen if the keyword is #:never)
Beta Was this translation helpful? Give feedback.
All reactions