How do I create an unbox instance of an ADT?
Asked Answered
I

2

6

I'm having trouble finding good resources that work for how to make my data types unboxed, for use in an unboxed vector. How would I make the data type

data Color = Yellow | Red | Green | Blue | Empty deriving (Show, Eq)

be an instance of Unbox?

Edit: after poking around a bit more, it seems that by forcing paramaters in some functions to be strict, I can convince GHC to unbox them automatically. If this applicable in my case? How do I know which paramaters to make strict?

Intendant answered 28/11, 2012 at 7:35 Comment(5)
Have you looked at this answer?Prelusive
Yes, GHCi told me Vector, MVector, and U.Unbox are not derivable classes. Not to mention I don't really understand what is going on there, especially with the GeneralizedNewtypeDeriving thing, and I'd like to understand things before I use them.Intendant
Not that it answers your question, but have you tried working with boxed vectors here? They'll handle your data type without hassle.Uno
Of course. Extrating the values from the vector is still taking up about 12% of the time in my program though, and unboxing the vector seems like the way to reduce that.Intendant
A simple workaround is to use integers wrapped into a newtype (like newtype Color = Color Int) instead of an enumerated data type. And then add helper functions for constructing/deconstructing instances. It's not very nice, but if performances is important, it could help. See Performance-Data types-Enumerations.Cranwell
S
9

You can use the vector-th-unbox package to derive the instance for you. You just need to provide conversion functions to and from some existing Unbox type:

colorToWord8 :: Color -> Word8
colorToWord8 = ...

word8ToColor :: Word8 -> Color
word8ToColor = ...

derivingUnbox "Color"
  [t| Color -> Word8 |]
  colorToWord8
  word8ToColor
Sheik answered 28/11, 2012 at 12:28 Comment(0)
U
0

GeneralizedNewtypeDeriving won't help you here because you're dealing with a 'full-blown' ADT, rather than a newtype wrapping something that's already an instance of Unbox.

Your data type is more suited to boxed vectors. Use Data.Vector.Unboxed if you need to hold more primitive numeric types like Doubles, Ints, etc. Perhaps you can make Color an instance of Unbox, but it almost certainly isn't worth the hassle. Import Data.Vector and you'll be set:

import qualified Data.Vector as V

Color = Red | Blue deriving Show

someColors :: V.Vector Color
someColors = V.fromList [Red, Blue, Blue, Red]
Uno answered 28/11, 2012 at 8:37 Comment(1)
As I mentioned in a previous comment, getting data out of my regular boxed vector was taking up 12% of the time in my program. I'd like to eliminate some of that by switching to unboxed.Intendant

© 2022 - 2024 — McMap. All rights reserved.