struct Tuple2[A, B] {
	a A
	b B
}

// map to array of Tuple2[int, Tuple2[key, value]] tuples
fn map_to_array_int_kv[K, V](m map[K]V) []Tuple2[int, Tuple2[K, V]] {
	mut r := []Tuple2[int, Tuple2[K, V]]{cap: m.len}
	mut i := 0
	for k, v in m {
		r << Tuple2[int, Tuple2[K, V]]{i, Tuple2[K, V]{k, v}}
		i += 1
	}
	return r
}

// map to array of Tuple2[int, Tuple2[Tuple2[key, value], Tuple2[value, key]]] tuples
fn map_to_array_int_kv_vk[K, V](m map[K]V) []Tuple2[int, Tuple2[Tuple2[K, V], Tuple2[V, K]]] {
	mut r := []Tuple2[int, Tuple2[Tuple2[K, V], Tuple2[V, K]]]{cap: m.len}
	mut i := 0
	for k, v in m {
		r << Tuple2[int, Tuple2[Tuple2[K, V], Tuple2[V, K]]]{i, Tuple2[Tuple2[K, V], Tuple2[V, K]]{Tuple2[K, V]{k, v}, Tuple2[V, K]{v, k}}}
		i += 1
	}
	return r
}

fn main() {
	x := {
		'one': 1
		'two': 2
	}
	y := {
		3: 'three'
		4: 'four'
	}

	println(x)
	rx1 := map_to_array_int_kv(x)
	println(rx1)
	rx2 := map_to_array_int_kv_vk(x)
	println(rx2)

	println(y)
	ry1 := map_to_array_int_kv(y)
	println(ry1)
	ry2 := map_to_array_int_kv_vk(y)
	println(ry2)

	// test typeof(X).name
	zx1 := []Tuple2[int, Tuple2[string, int]]{}
	println(typeof(zx1).name)
	zx2 := []Tuple2[int, Tuple2[Tuple2[string, int], Tuple2[int, string]]]{}
	println(typeof(zx2).name)
}
