union Pair<T,U> {
pair(T, U)
}
fun first<T, U>(p:Pair<T,U>) {
switch p {
case pair(x, y) {
x
}
}
}
fun second<T, U>(p:Pair<T,U>) {
switch p {
case pair(x, y) {
y
}
}
}
fun pairfun<T1, T2, U1, U2>(f:(fn T1 -> T2), g:(fn U1 -> U2)) {
fun p:Pair<T1,U1> {
pair(f(first(p)), g(second(p)))
}
}
first_pair: (all T:type, U:type, x:T, y:U. first(pair(x, y)) = x)
second_pair: (all T:type, U:type, x:T, y:U. second(pair(x, y)) = y)