Question

I'm trying to use fromPtr from accelerate-io to scoop an image out of OpenCV and into an Accelerate array. The documentation for this feature is obtuse, and this example won't compile (I can't install accelerate-examples because of Criterion). This code:

import Foreign.Ptr
import Foreign.C.Types

import AI.CV.CxCore
import AI.CV.HighGui

import Data.Array.Accelerate as A
import Data.Array.Accelerate.IO as A
import Data.Word

main :: IO ()
main = do
  capture <- cvCreateCameraCapture 0
  frame <- cvQueryFrame capture
  imgPtr <- cvGetImage frame -- Ptr IplImage -> Ptr Word
  arr <- A.fromPtr (Z :. 480 :. 640) ((), castPtr imgPtr)
  return ()

results in Couldn't match expected type 'BlockPtrs (EltRepr e0)' with actual type '((), Ptr b0)'. The type variables 'e0', 'b0' are ambiguous.

Removing the castPtr gives me Couldn't match expected type 'BlockPtrs (EltRepr e0)' with actual type '((), Ptr Word8)'. The type variable 'e0' is ambiguous.

Looking at the definitions for BlockPtrs and EltRepr only makes me more confused. But, adding a type signature to the expression, as in (((), imgPtr) :: BlockPtrs ((), Word8)) gives an expected type of BlockPtrs (EltRepr e0) and an actual type of BlockPtrs ((), Word8).

Does anyone here have experience with fromPtr?

EDIT: Getting closer. I tried to use the constructor EltRepr before, but it didn't occur to me to import its originating module. D'oh! But, now that I have done so, replacing the type signature with :: BlockPtrs (EltRepr Word8):

Couldn't match type `BlockPtrs (EltRepr e0)' with `((), Ptr Word8)'
The type variable `e0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Expected type: BlockPtrs (EltRepr e0)
  Actual type: BlockPtrs (EltRepr Word8)

EDIT: Answered by Reid Barton. It compiles for me now, thanks! "Final" code:

import AI.CV.CxCore
import AI.CV.HighGui

import Data.Array.Accelerate as A
import Data.Array.Accelerate.IO as A
import Data.Array.Accelerate.Array.Sugar (EltRepr)

main :: IO ()
main = do
  capture <- cvCreateCameraCapture 0
  frame <- cvQueryFrame capture
  imgPtr <- cvGetImage frame
  (arr :: Array (Z :. Int :. Int :. Int) Word8) <- A.fromPtr
      (Z :. 480 :. 640 :. 3)
      (((), imgPtr) :: BlockPtrs (EltRepr Word8))
  return ()
Was it helpful?

Solution

fromPtr :: (Shape sh, Elt e) => sh -> BlockPtrs (EltRepr e) -> IO (Array sh e)

GHC needs to know which type e you want to use fromPtr at to provide the Elt e instance.

Apparently EltRepr is a type family/associated type, so EltRepr e does not determine e. (There's no reason why there can't be two types e1 and e2 for which EltRepr e1 and EltRepr e2 are the same type.) So GHC can never conclude from the types of the arguments to fromPtr which type e to use.

Array is an ordinary type constructor, so Array sh e does determine e. So you should put a type ascription on arr instead.

  (arr :: Array (Z :. Int :. Int) Word8) <- A.fromPtr (Z :. 480 :. 640) ((), castPtr imgPtr)

(This will require some extension which GHC will let you know about.) Or, if you actually use arr in a way that determines the type of its elements to be Word8, you won't need this type ascription.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top