2009-06-10 10 views
10

diciamo che ho il seguente tipo:
Come creare unboxed esempio gamma mutevole

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

c'è un modo per creare uno di questi casi:

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

Per il momento ho memorizzare tutto come Word8 e faccio la conversione con (wrapped) fromEnum/toEnum, ma non mi sembra giusto. Ho bisogno di essere rigoroso e unboxing perché sto usando una grande struttura dati (> 1.2Go) in memoria, e non riesco a caricarla pigramente. Se non trovo alcuna soluzione ho intenzione di ri-implementare tutto in C++, che preferisco evitare per il mio progetto attuale.

Ho posto la domanda su #haskell ma non ho ricevuto risposta, forse non era il momento giusto per chiedere.

risposta

6

L'implementazione più semplice mi veniva in mente: basta avvolgere STUArray/IOUArray operazioni con 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 

Ora è possibile

import UnpackedEnumArray 
main = do 
    a <- newArray (0,9) Constructor0 :: IO (IOUEArray Int MyType) 
    getAssocs a >>= print 

Allo stesso modo, IArray casi potrebbe essere banalmente scritto pure.

+0

Grazie, non ho pensato di creare un nuovo tipo per questo, è un bel modo per farlo. –

1

Creare un'istanza per MArray IOUarray MyType IO dovrebbe essere possibile. Dai un'occhiata all'origine per la dichiarazione di istanza per MArray IOUarray Bool IO.

Poiché Bool è un'istanza sia di Enum sia di Bounded (e non molto altro), probabilmente utilizzano le funzioni di tali classi quando si crea l'istanza.

Potrebbe essere necessario derivare Bounded ma probabilmente non è un problema poiché gli array non in scatola possono contenere solo elementi di dimensione fissa.

Edit:

In this articolo si può leggere

È anche possibile implementare array disimballati te stesso per altri tipi semplici, tra cui enumerazioni.