Как создать распакованный экземпляр изменяемого массива

StackOverflow https://stackoverflow.com/questions/976936

  •  13-09-2019
  •  | 
  •  

Вопрос

допустим, у меня есть следующий тип :

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

Редактировать:

В это статью, которую можно прочитать

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top