import Base # A duplicable proof-only description of an array. Never used by the hash. type Tree is Data: Leaf{value: U32} Node{left: Tree, right: Tree} def thaw(t: Tree) -> Array: match t: case Leaf{x}: ALeaf{x} case Node{l,r}: ANode{thaw(l),thaw(r)} # Consume any linear array once, retaining a proof of its exact representation. law reify: for a: Array Sigma<&2,&1,Tree,t => {a == thaw(t) : Array}> law reify_node: for -l: Array for -r: Array for left: Sigma<&2,&1,Tree,t => {l == thaw(t) : Array}> for right: Sigma<&2,&1,Tree,t => {r == thaw(t) : Array}> Sigma<&2,&1,Tree,t => {ANode{l,r} == thaw(t) : Array}> def reify_node(l,r,left,right): match left right: case Tuple{+lt,lp} Tuple{+rt,rp}: (Node{lt,rt}, Equal.trans(Array,ANode{l,r},ANode{thaw(lt),r},ANode{thaw(lt),thaw(rt)}, Equal.cong(Array,Array,x => ANode{x,r},l,thaw(lt),lp), Equal.cong(Array,Array,x => ANode{thaw(lt),x},r,thaw(rt),rp))) def reify(a): match a: case ALeaf{+x}: (Leaf{x},{==}) case ANode{l,r}: reify_node(l,r,reify(l),reify(r))