Как создать распакованный экземпляр ADT?

У меня возникли проблемы с поиском хороших ресурсов, которые помогут сделать мои типы данных распакованными для использования в распакованном векторе. Как бы я сделал тип данных

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

быть экземпляром Unbox?

Редактировать: немного поковырявшись, кажется, что, заставив параметры в некоторых функциях быть строгими, я могу убедить GHC распаковать их автоматически. Если это применимо в моем случае? Как узнать, какие параметры сделать строгими?


person Drew    schedule 28.11.2012    source источник
comment
Вы смотрели этот ответ?   -  person Fixnum    schedule 28.11.2012
comment
Да, GHCi сказал мне, что Vector, MVector и U.Unbox не являются производными классами. Не говоря уже о том, что я действительно не понимаю, что там происходит, особенно с GeneralizedNewtypeDeriving, и я хотел бы понять некоторые вещи, прежде чем использовать их.   -  person Drew    schedule 28.11.2012
comment
Не то чтобы это отвечало на ваш вопрос, но пробовали ли вы здесь работать с векторами в штучной упаковке? Они без проблем обработают ваш тип данных.   -  person jtobin    schedule 28.11.2012
comment
Конечно. Извлечение значений из вектора по-прежнему занимает около 12% времени в моей программе, и распаковка вектора кажется способом уменьшить это.   -  person Drew    schedule 28.11.2012
comment
Простой обходной путь — использовать целые числа, заключенные в новый тип (например, newtype Color = Color Int), вместо перечисляемого типа данных. А затем добавьте вспомогательные функции для построения/деконструкции экземпляров. Это не очень приятно, но если выступления важны, это может помочь. См. Производительность-Типы данных-Перечисления.   -  person Petr    schedule 28.11.2012


Ответы (2)


Вы можете использовать vector-th-unbox, чтобы получить экземпляр для вас. Вам просто нужно предоставить функции преобразования в и из некоторого существующего типа Unbox:

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

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

derivingUnbox "Color"
  [t| Color -> Word8 |]
  colorToWord8
  word8ToColor
person hammar    schedule 28.11.2012

GeneralizedNewtypeDeriving здесь вам не поможет, потому что вы имеете дело с "полноценным" ADT, а не с новым типом, обертывающим что-то, что уже является экземпляром Unbox.

Ваш тип данных больше подходит для векторов в штучной упаковке. Используйте Data.Vector.Unboxed, если вам нужно хранить более примитивные числовые типы, такие как Doubles, Ints и т. д. Возможно, вы можете сделать Color экземпляром Unbox, но это почти наверняка не стоит проблема. Импортируйте Data.Vector, и все будет готово:

import qualified Data.Vector as V

Color = Red | Blue deriving Show

someColors :: V.Vector Color
someColors = V.fromList [Red, Blue, Blue, Red]
person jtobin    schedule 28.11.2012
comment
Как я упоминал в предыдущем комментарии, получение данных из моего обычного вектора в штучной упаковке занимало в моей программе 12% времени. Я хотел бы избавиться от некоторых из них, переключившись на распаковку. - person Drew; 28.11.2012