Haskell repa --- отображение с индексами - PullRequest
9 голосов
/ 05 июня 2011

Представьте, что я хочу отобразить функцию в массиве, но функция имеет тип не просто a -> b, а a -> Int -> b, т.е. функция также получает индекс.Как мне это сделать?

Ответы [ 3 ]

8 голосов
/ 05 июня 2011

Хороший вопрос, и он не был задокументирован в Репа-учебнике , поэтому я обновил его новым разделом прохождения .

В частности, traverse позволяет:

  • изменять форму выходного массива
  • индексировать любое значение
  • наблюдать текущий элемент

Это означает, что вы можете делать такие вещи, как:

Заменить все элементы с указателем их строки

> traverse a id (\_ (Z :. i :. j :. k) -> i) 
[0,0,0,0,0,0,0,0,0
,1,1,1,1,1,1,1,1,1
,2,2,2,2,2,2,2,2,2]

Умножить элемент на его строку

> traverse a id (\f (Z :. i :. j :. k) -> f (Z :. i :. j :. k) * i) 
[0,0,0,0,0,0,0,0,0
,10,11,12,13,14,15,16,17,18
,38,40,42,44,46,48,50,52,54]

И так далее.travese очень мощный и магически параллельный.

Advanced: параллельная десатурация изображения

Пример из учебника Repa

8 голосов
/ 05 июня 2011

Краткий ответ, используйте traverse.

Более длинный пример:

import qualified Data.Array.Repa as A
import qualified Data.Vector.Unboxed as U

arr1 :: A.Array A.DIM2 Double
arr1 = A.fromVector (A.Z A.:. 2 A.:. 3) $ U.fromList [1::Double,2,3,4,5,6]

arr2 :: A.Array A.DIM2 Double
arr2 = A.traverse arr1 id (\lf i@(A.Z A.:. r A.:. c) -> 
                  (lf i) + (fromIntegral r) + (fromIntegral c))  

arr1 - матрица 2x3.traverse - это функция, которая принимает (1) исходный массив, (2) функцию для отображения исходных индексов на целевые индексы и (3) функцию, которой дают (i) функцию поиска в исходном массиве и (ii)) индекс, который возвращает новое значение.

Так что здесь arr2 изменяет каждый из исходных элементов, добавляя индексы строк и столбцов этой конкретной записи.

1 голос
/ 01 июля 2017

Используйте zipWith

zipWith (\idx ele -> if even idx then div ele 2 else ele) [0..] xs
...