Итак, у меня много проблем с записью программы для создания ковариационной матрицы из нескольких больших целых векторов, хранящихся в отдельных файлах. Я начал с написания
mean xs = realToFrac (sum xs) / realToFrac (length xs)
cov xs ys = mean (zipWith (*) xs ys) - mean xs * mean ys
covmat vectors = [cov xs ys | ys <- vectors, xs <- vectors]
который работал для небольшого ввода, но вы можете видеть, насколько неэффективен даже "средний". Он сохраняет все xs в памяти при выполнении суммы, потому что они будут использоваться по длине. Thats fixable, так:
mean xs = realToFrac thisSum / realToFrac thisLength
where (thisSum, thisLength) = foldl' (\(s,l) y-> (s+y,l+1)) (0,0) xs
но затем я столкнулся с той же проблемой с "cov" . Когда я переписал "cov" в этом стиле, он не закончил использовать мою "среднюю" функцию. И у меня все еще есть один уровень, чтобы подняться, когда я напишу функцию "covmat", которая станет чрезвычайно сложной.
Итак, у меня есть две цели, которые, похоже, находятся в конфликте:
-
Перемещайте каждый список один раз, не сохраняя его в памяти
-
Разбить "covmat" на более простые, значимые функции, в частности "cov" и "mean"
Я не вижу никакого способа объединить эти два цели с тем, что я знаю о Haskell. Но концептуально это кажется простым: все эти функции должны "слушать" значения тех же немногих списков, что и они. Есть ли способ в Haskell организовать его так? Если для этого требуется другая структура данных или дополнительная библиотека, я открыт для этого.