-- An tricky version of "inpre". -- For this version, the current method can find -- its injectivity, while the derived inverse runs in O(n^2) time. inpre(x) = inprePrim(x,Nil) inprePrim(BLeaf,ys) = Pair(Nil,ys) inprePrim(BNode(v,l,r),ys2) = let Pair(rs,ys1) = inprePrim(r,ys2) in let Pair(ls,ys ) = inprePrim(l,ys1) in let Pair3(xs,y,bs) = unSplitXs(ls,v,rs) in let Pair(Cons(x2,xs2),y2) = isEquiv(xs,y,bs) in Pair(Cons(x2,xs2), Cons(y2,ys)) letUSX(Pair(xs2,bs),y) = Pair3(Cons(y,xs2), y,Cons(True,bs)) unSplitXs(Nil,y,xs) = letUSX( copyFalses(xs),y ) unSplitXs(Cons(x,l), z, r) = let Pair3(xs,y,bs) = unSplitXs(l,z,r) in Pair3(Cons(x,xs),y,Cons(False,bs)) copyFalses( Nil ) = Pair(Nil,Nil) copyFalses(Cons(x,xs)) = let Pair(s,t) = copyFalses(xs) in Pair(Cons(x,s), Cons(False,t)) isEquiv( Nil, y, Nil ) = Pair(Nil,y) isEquiv(Cons(x,xs), y, Cons(b,bs)) = let Pair(x1,y1) = checkEquiv(x,y,b) in let Pair(xs1,y2) = isEquiv(xs,y1,bs) in Pair(Cons(x1,xs1), y2) checkEquiv(Z,Z,True) = Pair(Z,Z) checkEquiv(S(x),Z,False) = Pair(S(x),Z) checkEquiv(Z,S(y),False) = Pair(Z,S(y)) checkEquiv(S(x),S(y),b) = let Pair(x1,y1) = checkEquiv(x,y,b) in Pair(S(x1),S(y1))