让我说我有以下类型:
data MyType = Constructor0 | Constructor1 | Constructor2
deriving (Eq,Show,Enum)
有没有办法创建其中一个这样的实例:
MArray (STUArray s) MyType (ST s)
MArray IOUarray MyType IO
目前我将所有内容存储为Word8,然后使用(包装)fromEnum / toEnum进行转换,但感觉不对。我需要严格和拆箱,因为我在内存中使用大型数据结构(> 1.2Go),我无法懒得加载它。如果我找不到任何解决方案,我将重新实现C ++中的所有内容,我希望避免使用当前项目。
我已经在#haskell上提出了问题,但我没有得到回复,也许这不是当天的好时机。
答案 0 :(得分:6)
我能想到的最简单的实现:只需用STUArray
/ IOUArray
包裹fromEnum
/ toEnum
个操作。
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
module UnpackedEnumArray (STUEArray, IOUEArray) where
import Control.Monad.ST
import Data.Array.Base
import Data.Array.IO
import Data.Array.ST
data STUEArray s i e = STUEArray { fromSTUEArray :: STUArray s i Int }
instance (Enum e) => MArray (STUEArray s) e (ST s) where
getBounds = getBounds . fromSTUEArray
getNumElements = getNumElements . fromSTUEArray
newArray is = fmap STUEArray . newArray is . fromEnum
newArray_ = fmap STUEArray . newArray_
unsafeRead (STUEArray a) = fmap toEnum . unsafeRead a
unsafeWrite (STUEArray a) i = unsafeWrite a i . fromEnum
data IOUEArray i e = IOUEArray { fromIOUEArray :: IOUArray i Int }
instance (Enum e) => MArray IOUEArray e IO where
getBounds = getBounds . fromIOUEArray
getNumElements = getNumElements . fromIOUEArray
newArray is = fmap IOUEArray . newArray is . fromEnum
newArray_ = fmap IOUEArray . newArray_
unsafeRead (IOUEArray a) = fmap toEnum . unsafeRead a
unsafeWrite (IOUEArray a) i = unsafeWrite a i . fromEnum
现在你可以
import UnpackedEnumArray
main = do
a <- newArray (0,9) Constructor0 :: IO (IOUEArray Int MyType)
getAssocs a >>= print
同样,IArray
个实例也可以轻易编写。
答案 1 :(得分:1)
应该可以为MArray IOUarray MyType IO
创建一个实例。查看MArray IOUarray Bool IO
的实例声明的源代码。
由于Bool是Enum
和Bounded
的实例(而不是其他),因此在制作实例时,他们可能会使用这些类中的函数。
您可能必须派生Bounded
,但这可能不是问题,因为未装箱的数组只能包含固定大小的元素。
修改强>
在this文章中,您可以阅读
您甚至可以自己为其他简单类型实现未装箱的数组,包括枚举。