mode U structural :> O mode O ordered (* fake polymorphism *) type A[m] = +{'a : 1} type B[m] = +{'b : 1} type C[m] = +{'c : 1} decl fuse (x : A[m]) (y : B[m]) : A[m] * B[m] decl fuse (x : A[m]) (y : B[m]) : A[m] @ B[m] defn fuse x y = (x, y) inst fuse (x : A[O]) (y : B[O]) : A[O] * B[O] fail inst fuse (x : A[O]) (y : B[O]) : A[O] @ B[O] decl uncurry (f : A[m] -> B[m] -> C[m]) : (A[m] * B[m] -> C[m]) decl uncurry (f : A[m] \ B[m] \ C[m]) : (A[m] @ B[m] \ C[m]) defn uncurry f = fun p => match p with | (x, y) => f x y inst uncurry (f : A[O] -> B[O] -> C[O]) : (A[O] * B[O] -> C[O]) inst uncurry (f : A[O] \ B[O] \ C[O]) : (A[O] @ B[O] \ C[O]) decl curry (g : A[m] * B[m] -> C[m]) : A[m] -> B[m] -> C[m] decl curry (g : A[m] @ B[m] \ C[m]) : A[m] \ B[m] \ C[m] defn curry g = fun x => fun y => g (x, y) inst curry (g : A[O] * B[O] -> C[O]) : A[O] -> B[O] -> C[O] inst curry (g : A[O] @ B[O] \ C[O]) : A[O] \ B[O] \ C[O] type llist[m] = +{'nil : 1, 'cons : * } type rlist[m] = +{'nil : 1, 'cons : @ } decl append (l1 : llist[m]) (l2 : llist[m]) : llist[m] defn append l1 l2 = match l1 with | 'nil() => l2 | 'cons(, ) => 'cons(, ) inst append (l1 : llist[O]) (l2 : llist[O]) : llist[O] decl reverse (l2 : rlist[m]) (l1 : llist[m]) : rlist[m] defn reverse l2 l1 = match l1 with | 'nil() => l2 | 'cons(, ) => (* (l2 : rlist A) (x : A) (xs : llist A) : rlist A *) reverse ('cons(, )) xs inst reverse (l2 : rlist[O]) (l1 : llist[O]) : rlist[O] inst reverse (l2 : rlist[U]) (l1 : llist[U]) : rlist[U]