"Given a stream of tuples, return two streams. The
 first stream produces the first elements of the
 given tuples, and the second stream produces the
 remaining elements of the given tuples.
 
 Thus:
 
     unzip(tuples)[i]==[tuples[i].first,*tuples[i].rest]"
shared [{Head*}, {Tail*}] unzip<Element,Head,Tail>
        ({Tuple<Element|Head,Head,Tail>*} tuples)
        given Tail satisfies Element[]
        => [tuples.map((Tuple<Element|Head,Head,Tail> tuple) => tuple.first),
            tuples.map((Tuple<Element|Head,Head,Tail> tuple) => tuple.rest)];

"Given a stream of pairs, return two streams. The
 first stream produces the first elements of the
 given pairs, and the second stream produces the
 second elements of the given pairs.
 
 Thus:
 
     unzipPairs(pairs)[i]==[pairs[i][0],pairs[i][1]]"
shared [{First*}, {Second*}] unzipPairs<First,Second>
        ({[First,Second]*} pairs)
        => [pairs.map(([First,Second] pair) => pair[0]),
            pairs.map(([First,Second] pair) => pair[1])];

"Given a stream of entries, return two streams. The
 first stream produces the keys of the given entries, 
 and the second stream produces the items of the given 
 entries.
 
 Thus:
 
     unzipEntries(entries)[i]==[entries[i].key,entries[i].item]"
shared [{Key*}, {Item*}] unzipEntries<Key,Item>
        ({<Key->Item>*} entries)
        given Key satisfies Object
        given Item satisfies Object
        => [entries.map(Entry<Key,Item>.key),
            entries.map(Entry<Key,Item>.item)];