在未装箱的Vector中存储枚举类型

时间:2016-07-28 10:04:23

标签: haskell

假设我有这样的事情:

data Colour = Red | Blue | Green
   deriving (Eq, Ord, Enum, Bounded, Read, Show)

我想要一个未装箱Vector的{​​{1}}个。我显然无法直接执行此操作(因为Colour不是Colour的实例),但我也无法告诉我如何编写Unbox实例{ {1}}。 Unbox的文档似乎没有说明你是如何制作某个实例的(或者至少不是我理解的方式)。

1 个答案:

答案 0 :(得分:5)

一种方法是使用Data.Vector.Unboxed.Deriving,它使用模板Haskell根据具有Unbox个实例的现有类型为新类型定义正确的实例。

{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, TemplateHaskell #-}
module Enum where


import qualified Data.Vector.Unboxed as U
import Data.Vector.Generic.Base
import Data.Vector.Generic.Mutable
import Data.Vector.Unboxed.Deriving
import Data.Word



data Colour = Red | Blue | Green
   deriving (Eq, Ord, Enum, Bounded, Read, Show)

colourToWord8 :: Colour -> Word8
colourToWord8 c =
    case c of
      Red -> 0
      Blue -> 1
      Green -> 2

word8ToColour :: Word8 -> Colour
word8ToColour w =
    case w of
      0 -> Red
      1 -> Blue
      _ -> Green


derivingUnbox "Colour"
  [t| Colour -> Word8 |]
  [| colourToWord8 |]
  [| word8ToColour |]


test n = U.generate n (word8ToColour . fromIntegral . (`mod` 3))

当然这会浪费空间,因为我们只使用Word8中的8位中的2位。