1

我正在尝试这个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)

现在我想用"computeS"顺序改变"computeP " 。但是,当我尝试编译它时,会出现此错误:

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)

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

提前致谢。

4

1 回答 1

1

你做的一切几乎都是正确的。computeP您得到的错误是由于单子的事实,而computeS不是。如果您仔细比较它们的类型签名,那么让您感到困扰的差异是 for 的限制Monad m和返回类型m (Array r2 sh e)for 。长话短说,只是改变computeP(Array r2 sh e)computeS

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

至:

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

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

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

使用上面的符号(以及在后台使用do的事实)确保在第二次调用. 但是由于不使用 Repa 的并行调度程序,它没有这个问题,因此不需要使用 a 的该属性,并且这段代码可以正常工作:computePdeepSeqArrayrotated1computePcomputeSMonad

let rotated1 = computeS (rot180 v) :: Array F DIM3 Word8
    rotated2 = computeS (rot180 rotated1) :: Array F DIM3 Word8
于 2017-08-02T01:43:47.200 回答