Unboxed Vectors of newtype'd values

Bas van Dijk v.dijk.bas at gmail.com
Mon Jun 4 21:40:48 CEST 2012

On 4 June 2012 12:43, Simon Peyton-Jones <simonpj at microsoft.com> wrote:
> | I'd like some compiler support for abstracting over unboxed values in
> | general and e.g. generate Unbox instances automatically. Then we could
> | have other unboxed structures than Vector.
> Could someone post an example or two of the problem being described here?

The following is some boring code I wrote a while back at work for
storing UUIDs[1] in unboxed vectors:

{-# LANGUAGE MultiParamTypeClasses, TypeFamilies #-}

import Control.Monad (liftM)
import Data.Word (Word32)

import Data.UUID (UUID)
import qualified Data.UUID as UUID

import qualified Data.Vector.Unboxed         as VU
import qualified Data.Vector.Generic         as VG
import qualified Data.Vector.Generic.Mutable as VGM

newtype instance VU.MVector s UUID =
	MV_UUID (VU.MVector s (Word32, Word32, Word32, Word32))

newtype instance  VU.Vector UUID =
	V_UUID (VU.Vector (Word32, Word32, Word32, Word32))

instance VU.Unbox UUID

instance VGM.MVector VU.MVector UUID where
  {-# INLINE basicLength #-}
  {-# INLINE basicUnsafeSlice #-}
  {-# INLINE basicOverlaps #-}
  {-# INLINE basicUnsafeNew #-}
  {-# INLINE basicUnsafeReplicate #-}
  {-# INLINE basicUnsafeRead #-}
  {-# INLINE basicUnsafeWrite #-}
  {-# INLINE basicClear #-}
  {-# INLINE basicSet #-}
  {-# INLINE basicUnsafeCopy #-}
  {-# INLINE basicUnsafeGrow #-}
  basicLength (MV_UUID v) =
    VGM.basicLength v

  basicUnsafeSlice i n (MV_UUID v) =
    MV_UUID $ VGM.basicUnsafeSlice i n v

  basicOverlaps (MV_UUID v1) (MV_UUID v2) =
    VGM.basicOverlaps v1 v2

  basicUnsafeNew n =
    MV_UUID `liftM` VGM.basicUnsafeNew n

  basicUnsafeReplicate n uuid =
    MV_UUID `liftM` VGM.basicUnsafeReplicate n (UUID.toWords uuid)

  basicUnsafeRead (MV_UUID v) i =
    fromQuadruple `liftM` VGM.basicUnsafeRead v i

  basicUnsafeWrite (MV_UUID v) i uuid =
    VGM.basicUnsafeWrite v i (UUID.toWords uuid)

  basicClear (MV_UUID v) =
    VGM.basicClear v

  basicSet (MV_UUID v) uuid =
    VGM.basicSet v (UUID.toWords uuid)

  basicUnsafeCopy (MV_UUID v1) (MV_UUID v2) =
    VGM.basicUnsafeCopy v1 v2

  basicUnsafeMove (MV_UUID v1) (MV_UUID v2) =
    VGM.basicUnsafeMove v1 v2

  basicUnsafeGrow (MV_UUID v) n =
    MV_UUID `liftM` VGM.basicUnsafeGrow v n

instance VG.Vector VU.Vector UUID where
  {-# INLINE basicUnsafeFreeze #-}
  {-# INLINE basicUnsafeThaw #-}
  {-# INLINE basicLength #-}
  {-# INLINE basicUnsafeSlice #-}
  {-# INLINE basicUnsafeIndexM #-}
  {-# INLINE elemseq #-}
  basicUnsafeFreeze (MV_UUID v) =
    V_UUID `liftM` VG.basicUnsafeFreeze v

  basicUnsafeThaw (V_UUID v) =
    MV_UUID `liftM` VG.basicUnsafeThaw v

  basicLength (V_UUID v) =
    VG.basicLength v

  basicUnsafeSlice i n (V_UUID v) =
    V_UUID $ VG.basicUnsafeSlice i n v

  basicUnsafeIndexM (V_UUID v) i =
    fromQuadruple `liftM` VG.basicUnsafeIndexM v i

  basicUnsafeCopy (MV_UUID mv) (V_UUID v) =
    VG.basicUnsafeCopy mv v

  elemseq _ uuid z = VG.elemseq (undefined :: VU.Vector a) a
                   $ VG.elemseq (undefined :: VU.Vector a) b
                   $ VG.elemseq (undefined :: VU.Vector a) c
                   $ VG.elemseq (undefined :: VU.Vector a) d z
        (a,b,c,d) = UUID.toWords uuid

fromQuadruple :: (Word32, Word32, Word32, Word32) -> UUID
fromQuadruple (a,b,c,d) = UUID.fromWords a b c d



[1] http://hackage.haskell.org/packages/archive/uuid/1.2.5/doc/html/Data-UUID.html

More information about the Libraries mailing list