Как способ практиковать с векторной библиотекой в Haskell, я пытаюсь переписать алгоритм минимизации Nelder-Mead, который я ранее написал на C. До сих пор у меня было немного проблем с переводом некоторых векторных операций идиоматически.
Например, рассмотрим функцию, которая находит центроид из n векторов из списка n + 1 (отфильтровывая один индекс),
В C это можно записать как
static void get_centroid(double **s, int n, int iz,
double *C)
{
for (int i = 0; i < n+1; i++) {
if (i != iz) {
for (int j = 0; j < n; j++)
C[j] += s[i][j];
}
}
for (int j = 0; j < n; j++)
C[j] /= n;
}
Я попытался перевести это в Haskell, и в итоге появился следующий
import Data.Vector
import qualified Data.Vector as V
type Node = Vector Double
type Simplex = Vector Node
centroid :: Simplex -> Int -> Node
centroid s iz = V.map (/ (fromIntegral $ V.length s)) $ V.zipWith (-) v (s ! iz)
where v = V.foldl go V.empty s
where go a b = V.zipWith (+) a b
Я нахожу этот код совершенно неэлегантным, так как он не отражает сущность происходящей векторной алгебры (и также более неэффективен, так как я добавляю и вычитаю S [iz]).
Одним из решений было бы реализовать какой-то тип векторного пространства или использовать более конкретную библиотеку линейных алгебр, но поскольку это такие общие операции, мне было интересно, существует ли более идиоматическое "прямое" решение.