10

假设我有以下类型:

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 上提出了这个问题,但没有得到回复,也许现在不是提问的好时机。

4

2 回答 2

6

我能想到的最简单的实现:只需用/包装STUArray/IOUArray操作。fromEnumtoEnum

{-# 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实例也可以简单地编写。

于 2009-06-10T21:02:18.090 回答
1

做一个实例MArray IOUarray MyType IO应该是可能的。查看MArray IOUarray Bool IO.

由于 Bool 是两者的实例,Enum并且Bounded(仅此而已)它们在创建实例时可能会使用这些类中的函数。

您可能必须派生Bounded,但这可能不是问题,因为未装箱的数组只能包含固定大小的元素。

编辑:

这篇文章中可以阅读

您甚至可以自己为其他简单类型(包括枚举)实现未装箱的数组。

于 2009-06-10T17:58:18.023 回答