Я написал код на Haskell, который должен решить следующую проблему: у нас есть n файлов: f1, f2, f3 .... fn, и я вырезал эти файлы так, чтобы у каждого среза было 100 строк
f1_1, f1_2, f1_3 .... f1_m
f2_1, f2_2, .... f2_n
...
fn_1, fn_2, .... fn_k
наконец, я создаю специальный тип данных (Dags), используя кусочки следующим образом
f1_1, f2_1, f3_1, .... fn_1 => Dag1
f1_2, f2_2, f3_2, ..... fn_2 => Dag2
....
f1_k, f2_k, f3_k, ..... fn_k => Dagk
код, который я написал, начинается с вырезания всех файлов, затем он связывает i-тые элементы списка результатов и создает Dag, используя окончательный список результатов
это выглядит так
-- # take a filename and cut the file in slices of 100 lines
sliceFile :: FilePath -> [[String]]
-- # take a list of lists and group the i-th elements into list
coupleIthElement :: [[String]] -> [[String]]
-- # take a list of lines and create a DAG
makeDags :: [String] -> Dag
-- # final code look like this
makeDag_ :: [FilePath] -> [Dag]
makeDags files = map makeDags $ coupleIthElement (concat (map sliceFile files))
Проблема в том, что этот код неэффективен, потому что:
необходимо сохранить все файлы в памяти в виде списка
сборщик мусора не работает эффективно, так как все функции нуждаются в списке результатов предыдущей функции
Как я мог переписать свою программу, чтобы воспользоваться преимуществами работы сборщика мусора и Laziness of Haskell?
если невозможно или проще, что я могу сделать, чтобы хоть немного повысить эффективность?
спасибо за ответ
редактировать
coupleIthElement ["abc", "123", "xyz"]
должен вернуть ["a1x","b2y","c3z"]
причины. 100 строк выбираются произвольно с использованием определенных критериев для некоторого элемента линий, но я отказываюсь от этого аспекта, чтобы сделать задачу более легкой для понимания,
другое издание
data Dag = Dag ([(Int, String)], [((Int, Int), Int)]) deriving Show
test_dag = Dag ([(1, "a"),(2, "b"),(3, "c")],[((1,2),1),((1,3),1)])
test_dag2 = Dag ([],[])
первый список - каждая вершина, определяемая номером и меткой, второй список - ребра ((1,2),3)
означает ребро между вершинами 1 и 2 со стоимостью 3