
Expresso: A simple expressions language with polymorphic extensible row types - wtetzner
https://github.com/willtim/Expresso
======
daanx
Looks like a fun project, very nice :-)

For those interested in more of the beautiful theory on extensible row types,
this project seems to be based on an earlier paper I wrote on scoped labels:
[https://www.microsoft.com/en-us/research/wp-
content/uploads/...](https://www.microsoft.com/en-us/research/wp-
content/uploads/2016/02/scopedlabels.pdf)

~~~
willtim
Hi, author here, yes your paper was a huge inspiration and I really should add
a references section in the readme. The row types in Expresso use very simple
lacks constraints, similar to the old Hugs TREX system, and don't permit
duplicate/scoped labels. I felt this was also a pretty good sweet spot.

~~~
daanx
Thanks :-) TREX (by Mark Jones and Benedict Gaster) is great. The beauty is
that a lacks constraints can get translated to fields offsets at runtime
making it super efficient!

E.g. a type like:

foo :: r/x => { x :: int | r } -> int

foo r = r.x

Gets translated at runtime to a function where the lacks constraint r/x
becomes an actual offset parameter.

------
CuriousSkeptic
I’ve toyed with the idea of doing a language like this. With a small
difference, records would be the only way to express values and bindings.

There would be no need to think of currying and partial application of
functions as it would naturally follow from partially evaluating incomplete
record inputs.

Another (nice?) property would be that a value always comes with a name
binding. This no need to encode semantics of values purely as positions in
lists and tuples.

So a question then to an implementer, is this something you considered? Is
feasible?

~~~
willtim
I have considered using pattern bindings to easily create "field pun"
bindings.

For example, one can already introduce all the fields of a record as local
bindings, e.g.

let {..} = import "List.x"

or just a subset using, e.g.

let {reverse} = import "List.x"

Similarly for function argument bindings, e.g.

f {x, y} = x - y

The above is just syntactic sugar for:

f r = r.x - r.y

Such named arguments of course prevent arguments with the same type being
passed in the wrong order, e.g.

f {x=2, y=1}

There is still some minor work to be done to better support inline type
annotations on such patterns to make them more usable.

Your idea of unifying bindings with records is interesting and not something I
have considered.

~~~
CuriousSkeptic
Actually I even thought of unifying records and lambdas. Which could end up
with a concatenative language, where application is commutative.

Couldn’t find a syntax that made sense though...

~~~
garmaine
Do you have any notes on this? It is something I’m actively researching.

~~~
CuriousSkeptic
Not much. But basically a bit inspired by Cat (a stack based, typed,
concatenative language), and a thought that stacks could be replaced by first
class environments and rewriting, so you could have a concatenative language
with partial evaluation. Instead of the usual ordered parameter lists, and/or
curried functions with partial application, functions take environments and
produce environments. A program like "{a=1}{b=2}{c=a+b}" would evaluate to
"{c=3}". While "{b=2}{c=a+b}" evaluates to "{c=a+2}"

~~~
garmaine
So the values in the environment are single use? I’m going to think on this...

------
chombier
Nice! I like how unit/void arise naturally from empty record/sum types.

------
acjohnson55
It seems like there's just a global namespace of labels. This reminds me of
the situation in Javascript before symbols were introduced. I'm curious why
this choice was made?

~~~
willtim
Labels in Expresso are just type-level symbols. Label names can be re-used
over and over again in different records and variants. This works fine because
a name is not tired to any particular nominal type (like a constructor in
Haskell or Java).

~~~
acjohnson55
But it seems like it would be an error to concatenate two records with a name
clash, though, right?

~~~
willtim
Yes because duplicate labels are not allowed within the scope of a single
record (you can specify which one overrides the other, but perhaps we also
need a convenient rename syntax). This point was that different records can
happily contain the same field names. The situation is the same as SQL.

------
titanix2
Any chance that such kind of records will land in a mainstream language such
as C# or F# in less than a decade?

~~~
CuriousSkeptic
C#8 will have a kind of records. Not fully this kind of records, but perhaps
close enough to put pressure in that direction.

