Before we begin our elaboration story we look at working with named typing contexts and turning then into nameless ones.

Named Typing Context.

When we, eventually, write our function for elaboration we will use the following definition for a named typing context.

Context : Type
Context = SnocList (String,Ty)

Indexing Named Contexts

When looking at (efficient) De Bruijn indices we used AtIndex wrapped in Var to represent position within a typing context. To generate instances of AtIndex for a named context we need to know a priori what the name and type of the variable is.

To help with elaboration, we will use an intermediate structure Exists that helps us lookup values in a key-value store i.e. association list.

The type constructor for Exists takes as arguments the key, its associated value, and the store itself.

data Exists : (k   : key)
           -> (v   : value)
           -> (kvs : SnocList (key, value))
                  -> Type
  where

The two constructors follow that of Elem and AtIndex.

Here
States that we have found the key that holds the value.
    Here : (prf : x = y)
               -> Exists x v (xs :< (y,v))
There
establishes that the key of the last element does match the one we are looking for, the key must be earlier within the list.
    There : (prf   : x = y -> Void)
         -> (later : Exists x v  xs)
                  -> Exists x v (xs :< MkPair y w)

You might think: Why not use Elem or AtIndex directly? Well with those structures we are reasoning about the element in its entirety. That is, both the key and the value. With Exits we are reasoning about the key itself.

Checking for Bound Variables and their Types

With Exists we need a corresponding decidability proof to ensure we can construct instances of Exists.

Proof is by induction on terms, assuming that the type for keys itself is decidable for equality.

isBound : DecEq key
       => (k   : key)
       -> (xs  : SnocList (key,value))
              -> Dec (DPair value (\v => Exists k v xs))

Complete the decision procedure for isBound.

To do so, you will need to also proof that empty lists cannot contain keys:

emptyListNoKey : Exists k v Lin -> Void

Finally, when elaborating terms we will need to demonstrate uniqueness of exists. That is, proving that given two copies of the exact same lists of pairs and a key, the key will point to the same element in both lists.

unique : Exists k x xs
      -> Exists k y xs
      -> x === y

Proof is by induction on terms.

Complete the uniqueness proof for key lookup.