Search code examples
haskellrepa

why do I get a type error in this case with Data.Array.Repa.Algorithms.Matrix.mmultP?


I believe this boils down to a foolish type mistake, but I can't figure it out. I have the following code:

{-# LANGUAGE TypeOperators #-}

import qualified Data.Array.Repa as R
import System.Random
import Data.Random.Normal
import Data.List
import Data.Function 
import qualified Data.Array.Repa.Algorithms.Matrix as M

weights:: (Int,Int)->(Double,Double) -> R.Array R.U (R.Z R.:. Int R.:. Int) Double

weights (nodes,features) range = R.fromListUnboxed (R.Z R.:. nodes R.:. features) values
where 
    values = take (nodes * features) $ randomRs range gen
    gen = mkStdGen 1

powerIteration :: R.Array R.U (R.Z R.:. Int R.:. Int) Double -> R.Array R.U (R.Z R.:. Int R.:. Int) Double

powerIteration m = M.mmultP m rb 
    where 
        rb = weights (rows,1) (0,1)
        (R.Z R.:. _ R.:. rows) = R.extent m


 main = do 
    let matrix = weights (10,3) (0,1)
    print $ powerIteration matrix 

This will create a Repa representation of an 2D array with 10 rows and 3 columns, which I would like to take the dot product of (using M.mmultP) with a 1D array of random numbers (between 0,1) with column length equal to the row number of the 2D array. I get something similar to work in ghci, but this could will create this error;

Couldn't match type ‘R.Array R.U R.DIM2 Double’ with ‘Double’
Expected type: R.Array R.U ((R.Z R.:. Int) R.:. Int) Double
  Actual type: R.Array
                 R.U ((R.Z R.:. Int) R.:. Int) (R.Array R.U R.DIM2 Double)
In the expression: M.mmultP m rb
In an equation for ‘powerIteration’:
    powerIteration m
      = M.mmultP m rb
      where
          rb = weights (rows, 1) (0, 1)
          (R.Z R.:. _ R.:. rows) = R.extent m  

This is a type error, but I can't seem to figure it out. Could someone please help me?


Solution

  • Yes, comments where correct, IO monad should be there:

    {-# LANGUAGE TypeOperators #-}
    
    import Data.Array.Repa
    import System.Random
    import Data.List
    import Data.Function 
    import Data.Array.Repa.Algorithms.Matrix
    
    weights :: (Int, Int) -> (Double, Double) -> Array U (Z :. Int :. Int) Double
    weights (nodes, features) range = fromListUnboxed (Z :. nodes :. features) values
      where 
        values = take (nodes * features) $ randomRs range gen
        gen = mkStdGen 1
    
    powerIteration :: Array U (Z :. Int :. Int) Double -> IO (Array U (Z :. Int :. Int) Double)
    powerIteration m = mmultP m rb 
      where 
        rb = weights (rows,1) (0,1)
        (Z :. _ :. rows) = extent m
    
    
    main = do 
      let matrix = weights (10,3) (0,1)
      iter <- powerIteration matrix
      print iter