Как создать неупакованный экземпляр изменяемого массива
Скажем, у меня есть следующий тип:
data MyType = Constructor0 | Constructor1 | Constructor2
deriving (Eq,Show,Enum)
Есть ли способ создать один из таких экземпляров:
MArray (STUArray s) MyType (ST s)
MArray IOUarray MyType IO
На данный момент я сохраняю все как Word8 и делаю преобразование с (обернутым) из Enum / to Enum, но это не так. Мне нужна строгость и распаковка, потому что я использую большую структуру данных (>1.2Go) в памяти, и я не могу загружать ее лениво. Если я не найду никакого решения, я собираюсь заново реализовать все в C++, чего я предпочитаю избегать для моего текущего проекта.
Я задал вопрос по #haskell, но не получил ответа, может быть, сейчас не время спрашивать.
2 ответа
Самая простая реализация, о которой я мог подумать: просто обернуть 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
но это, вероятно, не проблема, поскольку неупакованные массивы могут содержать только элементы фиксированного размера.
Редактировать:
В этой статье можно прочитать
Вы даже можете самостоятельно реализовать распакованные массивы для других простых типов, включая перечисления.