achirkin / easytensor

Many-dimensional type-safe numeric ops
https://hackage.haskell.org/package/easytensor
BSD 3-Clause "New" or "Revised" License
46 stars 2 forks source link

PrimBytes instances for Foreign.C.Types #20

Closed Rotaerk closed 4 years ago

Rotaerk commented 5 years ago

For PrimBytes to be applied to FFI, instances for these C-types would be nice to have.

Rotaerk commented 4 years ago

I'd like to work on this. Is there a way you would recommend doing this other than writing the PrimBytes instances by hand? The C-types are just newtype wrappers, so I'd think they could just be newtype-derived, but it doesn't seem GeneralizedNewtypeDeriving can handle the PrimBytes class.

I wrote this for CChar, and I could do something similar for all the others, but is this the best way?

instance PrimBytes CChar where
    type PrimFields CChar = PrimFields Int8
    getBytes (CChar i8) = getBytes i8
    {-# NOINLINE getBytes #-}
    fromBytes off ba = CChar (fromBytes off ba)
    {-# INLINE fromBytes #-}
    readBytes = readArray
    {-# INLINE readBytes #-}
    writeBytes = writeArray
    {-# INLINE writeBytes #-}
    readAddr a s = case readAddr a s of (# s', i8 #) -> (# s', CChar i8 #)
    {-# INLINE readAddr #-}
    writeAddr (CChar i8) a = writeAddr i8 a
    {-# INLINE writeAddr #-}
    byteSize (CChar i8) = byteSize i8
    {-# INLINE byteSize #-}
    byteAlign (CChar i8) = byteAlign i8
    {-# INLINE byteAlign #-}
    byteFieldOffset p (CChar i8) = byteFieldOffset p i8
    {-# INLINE byteFieldOffset #-}
    indexArray ba i = CChar (indexArray ba i)
    {-# INLINE indexArray #-}
    readArray mba i s = case readArray mba i s of (# s', i8 #) -> (# s', CChar i8 #)
    {-# INLINE readArray #-}
    writeArray mba i (CChar i8) = writeArray mba i i8
    {-# INLINE writeArray #-}
achirkin commented 4 years ago

Are you sure GeneralizedNewtypeDeriving does not work for PrimBytes? If you tried to do that in another file, maybe GHC was just unprepared for the generated code without UnboxedTuples or MagicHash? Also, if you add these to Numeric.PrimBytes, you can add more tests into PrimBytesTest via adding the types here or here

Rotaerk commented 4 years ago

Ah I was too hasty and didn't read the errors I was getting closely enough. My change was as follows:

  1. Add {-# LANGUAGE GeneralizedNewtypeDeriving #-} to the extensions.
  2. Add import Foreign.C.Types to the imports.
  3. Add deriving instance PrimBytes CChar down where the PrimBytes instances are

When I compiled with GHC 8.6.5, it actually compiles fine (just tested), but when I compiled with GHC 8.4.4, I would get a bunch of errors about invalid kinds. But to resolve that, I just had to follow the suggestion in the error and enable the TypeInType extension as well... With that in place, it now compiles with that version as well.

I'll submit a pull request later.