from typing import List
from typing import Tuple
from typing import Callable


def flatten(list_of_lists: List[List]) -> Tuple[List, Callable]:
    """
    Flatten a list of lists, while keeping the necessary information to reconstruct it later on.
    Returns the flat list +  a function that can be called to reconstruct a flat list (same or different one)
    with the same nested structure as the original list_of_lists
    :param list_of_lists:
    :return:
    """
    # take note of the number of entries for each of the inner lists
    # this will allow us to reconstruct the nested structure later on
    inner_list_lengths = [len(inner_list) for inner_list in list_of_lists]

    # flatten the list
    flat_list = [item for inner_list in list_of_lists for item in inner_list ]

    # can call this function to reconstruct the nested structure
    def reconstruct(another_flat_list):
        reconstructed_list_of_lists = []

        index = 0
        for length in inner_list_lengths:
            reconstructed_list_of_lists.append(another_flat_list[index: index+length])
            index += length

        return reconstructed_list_of_lists

    return flat_list, reconstruct