Как свернуть массив Repa в произвольное значение?

Все функции сокращения Repa возвращаются к тем же типам, что и содержимое массива. Например:

foldAllP :: (Shape sh, Source r a, Elt a, Unbox a, Monad m) => (a -> a -> a) -> a -> Array r sh a -> m a
foldAllS :: (Shape sh, Source r a, Elt a, Unbox a) => (a -> a -> a) -> a -> Array r sh a -> a

Я хотел бы сложить массив repa в структуру данных, которую я могу передать в библиотеку графического интерфейса для рендеринга, то есть произвольное значение, но я не могу найти функцию в библиотеке для этого. Существует ли эта функция или мне нужно перебирать ячейки, используя [... | x <- [0..w-1], y <- [0..h-1]]?


person Ana    schedule 02.11.2015    source источник
comment
У вас есть конкретный пример того, что вы хотите сделать?   -  person ErikR    schedule 02.11.2015
comment
Вы можете использовать пакет hmatrix-repa для преобразования в массив hmatrix, который является неоперативным преобразованием в массив C-типа. Или вы можете просто скопировать код из hmatrix-repa, он такой маленький.   -  person vivian    schedule 02.11.2015
comment
Сворачивание массивов repa имеет смысл только в том случае, если функция является ассоциативной, а нулевое значение должно быть левым и правым идентификатором, потому что функции foldAllP и foldAllS не гарантируют порядка, в котором связаны элементы. На самом деле foldAllP мог свободно выбирать разные связи при каждом вызове.   -  person user2407038    schedule 02.11.2015
comment
@ErikR Я уже понял причину. В моем массиве Repa есть информация, предназначенная для графического отображения, и я хотел бы сложить ее в структуру данных, которую я могу передать в графическую библиотеку. На данный момент пользуюсь блеском.   -  person Ana    schedule 05.11.2015
comment
Если у вас есть конкретный пример, мы можем помочь вам написать наиболее эффективный код. Понимание списков не всегда является самым быстрым способом перебора матрицы.   -  person ErikR    schedule 05.11.2015


Ответы (1)


Repa не позволяет сворачиваться в каком-то конкретном направлении, потому что при параллельном вычислении:

foldAllP: Приложения оператора связаны произвольно.

С другой стороны, последовательное свертывание не должно накладывать ограничения на то, что аккумулятор должен быть того же типа, что и элементы массива, но, к сожалению, это также относится и к foldAllS.

Существует очень простой обходной путь: вернуться к базовому векторному пакету, а именно преобразовать массив repa в неупакованный вектор с помощью toUnboxed, а затем просто использовать vector. Что, очевидно, означает, что сворачивание не будет выполняться параллельно, но все равно будет намного быстрее, чем использование списков. Пример:

λ>  import qualified Data.Vector.Unboxed as V
λ> :t V.foldr
V.foldr :: Unbox a => (a -> b -> b) -> b -> Vector a -> b
λ> :t V.foldl
V.foldl :: Unbox b => (a -> b -> a) -> a -> Vector b -> a
λ> V.foldr ((&&) . (>0.5)) True $ toUnboxed repaArray
person lehins    schedule 14.03.2016