Can I load a Numeric.LinearAlgebra.Static vector from a pointer

85 views Asked by At

I want to pass double-arrays to/from a Fortran77 library with Foreign.Marshal.Array, but in my Haskell code, I want to use statically sized vectors from Numeric.LinearAlgebra.Static. My minimal example attempt is the below.

{-# LANGUAGE DataKinds #-}

import           Data.Proxy
import           Foreign.Marshal.Array
import           Foreign.Ptr
import           GHC.TypeNats
import           Numeric.LinearAlgebra.Static
import           Numeric.LinearAlgebra.Data hiding (R,vector)

store :: (KnownNat n) => R n -> IO (Ptr Double)
store = newArray  . toList . unwrap


load :: (KnownNat n) => Ptr Double -> IO (R n)
load p = do
    let k = fromIntegral $ natVal (Proxy :: Proxy n)
    doubles <- peekArray k p 
    return (vector doubles :: R n)

main = do
    let a = vector [1,5,2] :: R 3
    print a
    ptr <- store a
    print ptr
    b <- (load ptr) :: IO (R 3)
    print b

The store function works, but the load does not compile. It seems that the n in the function body is not matched to the n in the type declaration. Is it something about existentials -- a topic I have not grasped? I tried the ScopedTypeVariables but it did not help me. How to proceed?

1

There are 1 answers

0
LudvigH On

I flailed around wildly, and the following code fixed it.

I use the ScopedTypeVariables and an explicit forall n. in the the signature of load. I still have no real clue on why it works. So I'll refrain from makring this as an answer, in hope of someone else actually explaining a solution.

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}

import           Data.Proxy
import           Foreign.Marshal.Array
import           Foreign.Ptr
import           GHC.TypeNats
import           Numeric.LinearAlgebra.Static
import           Numeric.LinearAlgebra.Data hiding (R,vector)

store :: (KnownNat n) => R n -> IO (Ptr Double)
store = newArray  . toList . unwrap


load :: forall n. (KnownNat n) => Ptr Double -> IO (R n)
load p = do
    let k = fromIntegral $ natVal (Proxy :: Proxy n)
    doubles <- peekArray k p 
    return (vector doubles :: R n)

main = do
    let a = vector [1,5,2] :: R 3
    print a
    ptr <- store a
    print ptr
    b <- (load ptr) :: IO (R 3)
    print b