Search code examples
haskellrepa

Repa's slices and shapes


I'm having some trouble grasping repa's Slice module, and specifically how its types and families are used with the slice function. I believe an answer to the following would clear things up for me.

Suppose x has shape shapeOfList [m_0, m_1, …, m_{d-1}]. Given integers i < d and j < mi, how do I build something with a suitable type to be slice's second argument, that extracts a slice from x with shape shapeOfList [m_0, …, m_{i-1}, m_{i+1}, …, m_{d-1}] defined by freezing index number i at j?

Examples in the case d=2 would be:

  • i=0: extract row j
  • i=1: extract column j

Solution

  • let arr =  fromListUnboxed (ix2 3 3) [0..8] :: Array U DIM2 Double 
    

    shapeOfList transform a list to an index, for instance

    shapeOfList [2,2] == (ix2 2 2) -- (Z:. 2 :.2)

    xs ! shapeOfList [2,2] == 8.0 
    

    But the function slice takes a range of indexes and this range of indexes is represented in REPA using the keywords Any and All. For instance, to extract the nth row from a Matrix the syntax is

    nRow n =computeUnboxedS $ slice arr (Any :. n :. All) -- xs :: Array U DIM1 Double
     --   nRow 2 = fromList [6.0,7.0,8.0]
    

    To extract the nth column the Following notation is used

    nCol n = computeUnboxedS $ slice arr (Any :. n ) -- xs :: Array U DIM1 Double
    --  nCol 2 = fromList [2.0,5.0,8.0]
    

    It is confusing that in the REPA vocabulary the array index (Z:. i:. i) and the range of indexes (Any :. n :. All) are both called shapes, but one represent only one element index while the other represent an array of indexes.

    EDIT

    to extract the ith dimension from an array traverse seems the right function, for instance for 3-dimensions

    -- k = 3 and m = 0
    fun3D_i arr = traverse arr (\(Z :. _ :. j :. k ) -> (Z:. j :. k)) (\f (Z :. j :. k )  -> f (Z :. 0 :. j :. k ))`
    
    -- k = 3 and m = 1
    fun3D_j arr = traverse arr (\(Z :. i :. _ :. k ) -> (Z:. i :. k)) (\f (Z :. i :. k )  -> f (Z :. i :. 0 :. k )) 
    
    -- k = 3 and m = 2
    fun3D_k arr = traverse arr (\(Z :. i :. j :. _ ) -> (Z:. i :. j)) (\f (Z :. i :. j )  -> f (Z :. i :. j :. 0 ))
    

    and so on for higher dimensions. On the other hand, Template Haskell could help here to select the dimension that you want to extract.