REPA:computeS 和 computeP?

REPA: computeS and computeP?

我正在尝试这个 REPA 库,我想以两种方式处理图像,并行和顺序

我可以读取图像(使用其他库,DevIL)并使用 computeP(并行)处理它。这是代码(来自 haskell 的 wiki 上的示例)。

import Foreign.Ptr
import System.Environment
import Data.Word
import Data.Array.Repa hiding ((++))
import Data.Array.Repa.IO.DevIL
import Data.Array.Repa.Repr.ForeignPtr

main :: IO () 
main = do
    [f] <- getArgs
    (RGB v) <- runIL $ readImage f
    rotated <- (computeP $ rot180 v) :: IO (Array F DIM3 Word8)
    runIL $ writeImage ("flip-"++f) (RGB rotated)

rot180 :: (Source r e) => Array r DIM3 e -> Array D DIM3 e
rot180 g = backpermute e flop g
    where
        e@(Z :. x :. y :. _)   = extent g
        flop (Z :. i         :. j         :. k) =
             (Z :. x - i - 1 :. y - j - 1 :. k)

现在我想依次将 "computeP" 更改为 "computeS"。 但是,当我尝试编译它时,出现了这个错误:

Couldn't match expected type ‘IO (Array F DIM3 Word8)’
                with actual type ‘Array r20 DIM3 Word8’
    In a stmt of a 'do' block:
      rotated <- (computeS $ rot180 v) :: IO (Array F DIM3 Word8)

您可能猜到了,我是函数式编程的新手。我不知道为什么会发生此错误。任何帮助都会很棒。

提前致谢。

你做的几乎都是对的。您得到的错误是由于 computeP 是一元的,而 computeS 不是。如果你仔细比较它们的类型签名,你会发现的区别是 Monad m 限制和 return 类型 m (Array r2 sh e) for computeP vs (Array r2 sh e) for computeS.长话短说,只是改变

rotated <- (computeP $ rot180 v) :: IO (Array F DIM3 Word8)

至:

let rotated = (computeS $ rot180 v) :: (Array F DIM3 Word8)

Repa 中的并行计算必须是 monadic 的原因部分与惰性有关,但主要是 Repa 无法处理嵌套并行性。 Monad 的顺序 属性 解决了大部分问题:

rotated1 <- (computeP $ rot180 v) :: IO (Array F DIM3 Word8)
rotated2 <- (computeP $ rot180 rotated1) :: IO (Array F DIM3 Word8)

使用上面的 do 表示法(以及 computeP 在幕后使用 deepSeqArray 的事实)确保 rotated1 在第二次调用 computeP。但是由于 computeS 不使用 Repa 的并行调度程序,所以它没有那个问题,因此不需要使用 Monad 的 属性 并且这段代码可以正常工作:

let rotated1 = computeS (rot180 v) :: Array F DIM3 Word8
    rotated2 = computeS (rot180 rotated1) :: Array F DIM3 Word8