Как создать распакованный экземпляр изменяемого массива
Вопрос
допустим, у меня есть следующий тип :
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, но не получил ответа, возможно, сейчас было неподходящее время для вопросов.
Решение
Самая простая реализация, о которой я мог подумать:просто оберните 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
экземпляры также могут быть написаны тривиально.
Другие советы
Создание экземпляра для MArray IOUarray MyType IO
должно быть возможно.Взгляните на источник объявления экземпляра для MArray IOUarray Bool IO
.
Поскольку Bool является экземпляром обоих Enum
и Bounded
(и не более того) они, вероятно, используют функции из этих классов при создании экземпляра.
Возможно, вам придется вывести Bounded
но это, вероятно, не проблема, поскольку распакованные массивы могут содержать только элементы фиксированного размера.
Редактировать:
В это статью, которую можно прочитать
Вы даже можете самостоятельно реализовать распакованные массивы для других простых типов, включая перечисления.