concrete TreeDemo {
  @type run () -> ()
}

define TreeDemo {
  run () {
    TypeTree tree <- TypeTree.new()

    TypeKey<Int>    keyInt    <- TypeKey<Int>.new()
    TypeKey<String> keyString <- TypeKey<String>.new()
    TypeKey<Float>  keyFloat  <- TypeKey<Float>.new()
    TypeKey<Value>  keyValue  <- TypeKey<Value>.new()

    \ tree.set<?>(keyInt,1)
    \ tree.set<?>(keyString,"a")

    \ check<?>(tree,keyInt)
    \ check<?>(tree,keyString)
    \ check<?>(tree,keyFloat)  // Not found, since we never added a value.

    \ tree.set<?>(keyValue,Value.new())
    \ check<?>(tree,keyValue)
  }

  @category check<#x>
    #x requires Formatted
  (TypeTree,TypeKey<#x>) -> ()
  check (tree,key) {
    scoped {
      optional #x value <- tree.get<#x>(key)
    } in if (present(value)) {
      \ LazyStream<Formatted>.new()
          .append("Found '")
          .append(require(value))
          .append("'\n")
          .writeTo(SimpleOutput.stderr())
    } else {
      \ LazyStream<Formatted>.new()
          .append(typename<TypeKey<#x>>())
          .append(" Not Found\n")
          .writeTo(SimpleOutput.stderr())
    }
  }
}

concrete Value {
  refines Formatted
  @type new () -> (Value)
}

define Value {
  new () { return Value{} }
  formatted () { return "Value" }
}