Сортировка действительно выглядит так, как будто она вызовет много выделений. Хотя сортировка выполняется по списку, ее нельзя полностью изменить, поскольку сортировка списков приводит к созданию множества промежуточных списков. При необходимости вы можете попробовать выполнить сортировку на MVector
, используя, например, пакет vector-алгоритмы , который обеспечивает эффективные алгоритмы сортировки.
Однако есть и другие недостатки, которые вызывают большее выделение, чем необходимо в
Data.Vector.Unboxed.fromList . take n . List.sortBy (flip $ Ord.comparing id)
$ [ ( sum [ (c + a) * wsum z | (z,c) <- IntMap.toList zt_d ] , d)
| d <- IntMap.keys $ m
, let zt_d = IntMap.findWithDefault IntMap.empty d $ m ]
Когда вы пишете
d <- IntMap.keys m, let zt_d = IntMap.findWithDefault IntMap.empty d m
-- The '$' are unnecessary, I left them out
вы: 1) пересекаете всю карту, чтобы собрать список ключей, и 2) затем ищите каждый ключ самостоятельно. Поскольку вы просматриваете только ключи, присутствующие на карте, вы никогда не используете значение по умолчанию. Гораздо эффективнее создать список пар ключ / значение в одном обходе карты:
(d,zt_d) <- IntMap.assocs m
Тогда, если id
в flip $ Ord.comparing id
действительно является тождественной функцией, это было бы более читабельным (и, возможно, более эффективным), как sortBy (flip compare)
.
В зависимости от типа суммируемых элементов (и, возможно, уровня оптимизации), может быть лучше использовать Data.List.foldl' (+) 0
вместо sum
.