---
# System prepended metadata

title: Record MVP
tags: [juvix-project, records, Juvix]

---

# Record MVP

###### tags: `Juvix` `juvix-project` `records`

$$
\newcommand\Let{\mathbf{let}\:}
\newcommand\In{\:\mathbf{in}\:}
\newcommand\Return{\:\mathbf{return}\:}
\newcommand\RV[1]{\langle #1 \rangle}
\newcommand\Lett{\mathbf{let}\text-\RV{}}
$$

## Names

Implementing the [current design] of records still has some unanswered questions about the bound names $\bar y$ in $\Let \RV{\bar y} = e \dotsb$:

[current design]: https://hackmd.io/Xlvu82eFQ_m-cebUWAtGsw?view

- they are bound variables, so they must be added to the local context in dependency order
- in the current spec, they can be given in any order
- the name resolution step happens before type checking, so the information to reorder them is not yet available.

It might be possible to get around this by using `PatternVar` instead, but I understand that is on the way out at some point so adding more uses of it is probably not the right way to go.

With all this in mind, I think in the initial implementation we simply require (when checking the $\Lett$ expression) that the names $\bar y$ be in the same order as in the type of $e$. Allowing them to be permuted can be added in future.

With the names in the `let` corresponding exactly to those in the type of `e`, the  constructor can be

```
RecElim [Symbol]              -- names bound
        (Elim primTy primVal) -- record to deconstruct
        (Term primTy primVal) -- return type
        (Term primTy primVal) -- body
```

and the representation in core of $\Let \RV{\bar y} = e \Return x.A \In s$ can be `RecElim 𝑦̄ 𝑒 𝐴 𝑠`. One variable ($x$, corresponding to the record) is bound in `𝐴`, and one in `𝑠` for each field, with the rightmost field being index `0`.


## Field lookups

Since the $\Lett$ form is (I think) also going to be added to the frontend language, it could be possible to have that be the *only* way to eliminate a record in the MVP implementation, leaving lookup expressions and the passes required to later iterations.


## Do records have $η$?

Not yet, no, because the evaluator isn't type aware. When it is, then since these records are non-recursive, I don't see why they shouldn't.


## Renaming?

Sure. Not in the MVP, probably, but soon after.

Something like
`let {val = x} = e return ... in x`
desugaring to
`let {val} = e return ... in (let x = val in x)`.


## Does this design actually work?

I never gave an example before, so here's a couple

```
sig pair : (a : ty) -> (b : a -> ty) -> ty
let pair a b = {1 fst : a; 1 snd : b fst}

-- ω because the snd field is being dropped
sig fst : pair a b -(ω)-> a
let fst #a p = let {fst; snd} = p return _ => a in fst

sig snd : (p : pair a b) -(ω)-> b (fst p)
let fst #b p =
  let    {fst; snd} = p
  return x => (let {fst; snd} = x return ty in b fst)
  in     snd


sig two : ty -> ty
let two a = {2 val : a}

sig app : (a -> a -> b) -> two a -> b
let app #b f p =
  let {val} = p return _ => b in f val val
```

The body of `snd` looks a bit weird with the nested let, but that's because this is currently the unsugared core form. It would be possible to automatically have the fields be in scope in the `return` clause by adding a desugar step that inserts this extra `let`.


## Is the $x$ in $\Return x. A$ really needed?

I think so? But if not I'll be more than happy to remove it.