假设我有这样的事情:
data Colour = Red | Blue | Green
deriving (Eq, Ord, Enum, Bounded, Read, Show)
Run Code Online (Sandbox Code Playgroud)
我希望有一个未装箱Vector的Colours.我显然不能直接这样做(因为Colour它不是一个实例Unbox),但我也不知道我将如何编写Unbox实例Colour.文档Unbox似乎没有说明你是如何创建它的一个实例(或至少,不是我理解的方式).
一种方法是使用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))
Run Code Online (Sandbox Code Playgroud)
当然,在这种情况下这会浪费空间,因为我们只使用8位中的2位Word8.