packages feed

zeolite-lang-0.10.0.0: example/tree/type-tree.0rp

/* A key-value index that can hold multiple types of value.
 *
 * Each element in the index is keyed by a TypeKey that has a type param that
 * matches the type of the value.
 */
concrete TypeTree {
  // Creates a new TypeTree, e.g., TypeTree.new().
  @type new () -> (TypeTree)

  // Sets the value for the given key, inserting if necessary.
  @value set<#x> (TypeKey<#x>,#x) -> (TypeTree)

  // Removes the value for the given key.
  @value remove (TypeKey<any>) -> (TypeTree)

  // Returns the value for the given key, or empty if:
  // - There is no entry for the key.
  // - The value for the key is not of type #x, e.g., was originally added to
  //   the tree as a parent of type #x.
  @value get<#x> (TypeKey<#x>) -> (optional #x)
}

/* A typed key for indexing values in TypeTree.
 *
 * A key of type TypeKey<#x> indexes a value of type #x. The key can also be
 * used as a key for any parent type of #x. For example, if V -> I then
 * TypeKey<V> can be used as TypeKey<I>.
 */
concrete TypeKey<|#x> {
  // Note that TypeKey<#x> as a type argument for some #y can satisfy
  //
  //   #y defines LessThan<#y>
  //
  // even though we only define LessThan<TypeKey<any>>.
  //
  // This is non-trivial:
  //
  // - #x -> any, which is trivial.
  // - TypeKey<#x> -> TypeKey<any>, since TypeKey has a single covariant param.
  // - LessThan<TypeKey<any>> -> LessThan<TypeKey<#x>>, since LessThan has a
  //   single contravariant param.
  // - TypeKey<#x> -> LessThan<TypeKey<any>> -> LessThan<TypeKey<#x>>.
  //
  // This means that TypeKey<#x> can be used as a key in Tree. (See tree.0rp.)
  defines LessThan<TypeKey<any>>
  defines Equals<TypeKey<any>>

  // Creates a new TypeKey, e.g., TypeTree<#x>.new().
  @type new () -> (TypeKey<#x>)
}