However, just adding some syntax does not finish solving the problem: one still needs to figure out how to get everything to typecheck under all use cases (and all type extensions) and also to operate efficiently at runtime. This article does that (although it isn't actually explained that well in the article).
That's how OCaml records work, too.
Also a bit disappointed that it didn't make the cut - it seemed like a good pragmatic solution!
Nice record variants which completely solve this issue at the library level, IMO, exist. But the types are more complex than what most people want to deal with in practice.
map (\x -> x.slot) listOfFoos
Pretty sure that x has type `Foo` in this case.One could then simply disallow the use of `HasField "slot" b a` in the domain of functions (pretty sure it can never appear in the range). This would then require the programmer to provide annotations if a more concrete type can't be inferred.
Wouldn't update do that? Making up further syntax...
(\x -> prototype.slot = x) :: HasField "slot" b a => b -> a
Or am I missing what you meant by "appear in the range"? foo :: (Num a, HasField "slot" a b) => b -> b
foo x = x.slot <~ 1
Technically, depending upon the semantics of records (how anonymous they are) it could even be that the input argument has a different type as the output argument, e.g. foo {} ==> {slot = 1}
Anyway, there's a lot to be said here but I think that this isn't merely a syntactic difference. Even the idea that map (\x -> x.slot) listOfFoos
could be inferred would require mixing type inference and syntax de-sugaring.What I'm arguing is that anonymous records are unnecessary and it's silly to insist that problems with anonymous records should derail a good solution for concrete ones. But you are right that it's a bit more than just syntactic.
Since you should know the type of the first argument to '.', it is possible to disambiguate, but it would be a pretty significant corner case in the grammar.