[Haskell-cafe] broken IO support in uvector package, when using non primitive types

Daniel Fischer daniel.is.fischer at web.de
Fri Mar 13 19:18:59 EDT 2009


Am Freitag, 13. März 2009 23:53 schrieb Don Stewart:
> manlio_perillo:
> > Daniel Fischer ha scritto:
> >> [...]
> >> Worked with uvector-0.1.0.1:
> >>
> >>  [...]
> >> But not with uvector-0.2
> >>
> > > [...]
> >
> > The main difference is that in uvector 0.2, hPutBU does not write in the
> > file the length of the array; hGetBU simply use the file size.
> >
> >    let elemSize = sizeBU 1 (undefined :: e)
> >    n <- fmap ((`div`elemSize) . fromInteger) $ hFileSize h
> >
> >
> > So, the problem seems to be here.
> > This simply don't support having two arrays written in the same file,
> > and sizeBU belongs to the UAE class, whose instances are only declared
> > for builtin types.
> >
> >
> > So, the patch is: "just revert this change".
>
> Or... use your own UIO instance. That's why it's a type class!
>
> Anyway, for the background on this:
>
>     Tue Nov 18 08:44:46 PST 2008 Malcolm Wallace
>       * Use hFileSize to determine arraysize, rather than encoding it in
> the file.
>
>     "Here is a patch to the uvector library that fixes hGetBU and hPutBU to
>     use the filesize to determine arraysize, rather than encoding it within
>     the file.  I guess the disadvantages are that now only one array can
>     live in a file, and the given Handle must indeed be a file, not a
> socket Handle.  But the advantage is that one can read packed raw datafiles
> obtained externally."
>
> Still, again, I'd point out that uvector is alpha, APIs can and will
> change.
>
> -- Don

Though I don't really know whether what I did is sane, I can offer a few 
patches which seem to work. 
Check for sanity before applying :)

hunk ./Data/Array/Vector/Prim/BUArr.hs 85
-  hPutBU, hGetBU
+  hPutBU, hGetBU, hGetLengthBU

hunk ./Data/Array/Vector/Prim/BUArr.hs 864
+hGetLengthBU :: forall e. UAE e => Int -> Handle -> IO (BUArr e)
+hGetLengthBU numEntries h =
+  do
+    marr@(MBUArr _ marr#) <- stToIO (newMBU numEntries)
+    let bytes = sizeBU numEntries (undefined :: e)
+    wantReadableHandle "hGetBU" h $
+        \handle at Handle__{ haFD=fd, haBuffer=ref, haIsStream=is_stream } -> do
+      buf at Buffer { bufBuf = raw, bufWPtr = w, bufRPtr = r } <- readIORef ref
+      let copied    = bytes `min` (w - r)
+          remaining = bytes - copied
+          newr      = r + copied
+          newbuf | newr == w = buf{ bufRPtr = 0, bufWPtr = 0 }
+                 | otherwise = buf{ bufRPtr = newr }
+      --memcpy_ba_baoff marr# raw (fromIntegral r) (fromIntegral copied)
+      memcpy_ba_baoff marr# raw (fromIntegral r) (fromIntegral copied)
+      writeIORef ref newbuf
+      readChunkBU fd is_stream marr# copied remaining
+      stToIO (unsafeFreezeAllMBU marr)
+

hunk ./Data/Array/Vector/UArr.hs 59
-  BUArr, MBUArr, UAE,
-  lengthBU, indexBU, sliceBU, hGetBU, hPutBU,
+  BUArr, MBUArr, UAE(..),
+  lengthBU, indexBU, sliceBU, hGetBU, hGetLengthBU, hPutBU,

hunk ./Data/Array/Vector/UArr.hs 867
+  hGetLengthU :: Int -> Handle -> IO (UArr a)

hunk ./Data/Array/Vector/UArr.hs 875
+primGetLengthU :: UPrim a => Int -> Handle -> IO (UArr a)
+primGetLengthU n = liftM mkUAPrim . hGetLengthBU n
+

hunk ./Data/Array/Vector/UArr.hs 880
-instance UIO Bool   where hPutU = primPutU; hGetU = primGetU
-instance UIO Char   where hPutU = primPutU; hGetU = primGetU
-instance UIO Int    where hPutU = primPutU; hGetU = primGetU
-instance UIO Word   where hPutU = primPutU; hGetU = primGetU
-instance UIO Float  where hPutU = primPutU; hGetU = primGetU
-instance UIO Double where hPutU = primPutU; hGetU = primGetU
+instance UIO Bool   where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Char   where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Int    where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Word   where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Float  where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Double where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU

hunk ./Data/Array/Vector/UArr.hs 887
-instance UIO Word8  where hPutU = primPutU; hGetU = primGetU
-instance UIO Word16 where hPutU = primPutU; hGetU = primGetU
-instance UIO Word32 where hPutU = primPutU; hGetU = primGetU
-instance UIO Word64 where hPutU = primPutU; hGetU = primGetU
+instance UIO Word8  where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Word16 where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Word32 where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Word64 where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU

hunk ./Data/Array/Vector/UArr.hs 892
-instance UIO Int8   where hPutU = primPutU; hGetU = primGetU
-instance UIO Int16  where hPutU = primPutU; hGetU = primGetU
-instance UIO Int32  where hPutU = primPutU; hGetU = primGetU
-instance UIO Int64  where hPutU = primPutU; hGetU = primGetU
+instance UIO Int8   where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Int16  where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Int32  where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU
+instance UIO Int64  where hPutU = primPutU; hGetU = primGetU; hGetLengthU = 
primGetLengthU

hunk ./Data/Array/Vector/UArr.hs 899
-instance (UIO a, UIO b) => UIO (a :*: b) where
+instance (UAE a, UAE b, UIO a, UIO b) => UIO (a :*: b) where

hunk ./Data/Array/Vector/UArr.hs 902
-  hGetU h                = do xs <- hGetU h
-                              ys <- hGetU h
+  hGetU h                = do let elemSize = sizeBU 1 (undefined :: a) + 
sizeBU 1 (undefined :: b)
+                              n <- fmap ((`div` elemSize) . fromInteger) $ 
hFileSize h
+                              xs <- hGetLengthU n h
+                              ys <- hGetLengthU n h
+                              return (UAProd xs ys)
+  hGetLengthU n h        = do xs <- hGetLengthU n h
+                              ys <- hGetLengthU n h

hunk ./Data/Array/Vector/UArr.hs 914
-instance (RealFloat a, UIO a) => UIO (Complex a) where
+instance (RealFloat a, UAE a, UIO a) => UIO (Complex a) where

hunk ./Data/Array/Vector/UArr.hs 918
+  hGetLengthU n h         = do arr <- hGetLengthU n h
+                               return (UAComplex arr)

hunk ./Data/Array/Vector/UArr.hs 921
-instance (Integral a, UIO a) => UIO (Ratio a) where
+instance (Integral a, UAE a, UIO a) => UIO (Ratio a) where

hunk ./Data/Array/Vector/UArr.hs 925
+  hGetLengthU n h         = do arr <- hGetLengthU n h
+                               return (UARatio arr)




More information about the Haskell-Cafe mailing list