I was thinking about how to implement newtypes in polaris. I want these to work mostly like they do in Haskell, but with one small change.
To make newtypes over records actually somewhat pleasant to use, I would like to be able to access fields ‘through’ the newtype like this (as long as the constructor is public)
newtype Blah = Blah { x : Int, y : Bool }
let blah = Blah { x = 1, y = true }
blah.x # I want this to typecheck and return an integer!The issue here is that polaris’ type checker is constraint based, so this is less obvious than it looks.
With a single pass typechecker, this would be pretty easy! Instead of a more traditional row polymorphic rule for record access1,
I could just infer the type of
e
and do some ad-hoc magic if it is known to be a record newtype at this
point.
This immediately breaks down with constraints though. Consider this example:
let blah = Blah { x = 1, y = true }
let ohno = id(blah)
ohno.xWith the system above, this would not be accepted.
id(blah) instantiates the polymorphic function
id, so ohno is assigned the type
α and a constraint α ~ Blah is emitted.
Because constraints are not solved immediately, this means that when
inferring the type for ohno.x, ohno still has
type α and the typechecker cannot know that it will have
type Blah in the future!
I have a solution for this, but it feels a bit hacky. If there is a better way to do this, I would love to hear about it!
So, just like in the revised rule above, this rule for record access
infers the type of e, but instead of immediately looking at
the type or checking against a record type, it emits a new kind of
constraint.
Where the constraint solver rules for these (x : τ) ∈ τ
constraints look something like this
The last line essentially defaults to a record type, so that
expressions like \r -> r.x still infer the regular row
polymorphic type forall a. { x : a | r } -> a
Apologies for the off-center latex. I couldn’t get webtex to accept
\begin{center}↩︎
