2009-06-10 2 views
10

Допустим, у меня есть следующий тип:
Как создать Unboxed изменяемый экземпляр массива

 
data MyType = Constructor0 | Constructor1 | Constructor2 
      deriving (Eq,Show,Enum) 

Есть ли способ, чтобы создать одну из таких случаев:

 
MArray (STUArray s) MyType (ST s) 
MArray IOUarray MyType IO 

На данный момент я хранить все как Word8, и я делаю преобразование с помощью (wrapped) fromEnum/toEnum, но это не кажется правильным. Мне нужно строгость и unboxing, потому что я использую большую структуру данных (> 1.2Go) в памяти, и я не могу загрузить ее лениво. Если я не найду какое-либо решение, я собираюсь повторно реализовать все на C++, чего я предпочитаю избегать для своего текущего проекта.

Я задал вопрос о #haskell, но я не получил ответа, может быть, это было не самое подходящее время дня.

ответ

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 экземпляры могут быть тривиальным написаны, а также.

+0

Спасибо, я не думал о создании нового типа для этого, это хороший способ сделать это. –

1

Изготовление экземпляра для MArray IOUarray MyType IO должно быть возможным. Взгляните на источник для объявления экземпляра для MArray IOUarray Bool IO.

Поскольку Bool является экземпляром как Enum, так и Bounded (и не намного больше), они, вероятно, используют функции из этих классов при создании экземпляра.

Возможно, вам придется получить Bounded, но это, вероятно, не проблема, так как массивы unboxed могут содержать только элементы фиксированного размера.

Edit:

В this статьи можно прочитать

Вы можете даже реализовать Unboxed массивам себя для других простых типов, в том числе перечислений.