2009-06-10 4 views
10

disons que j'ai le type:
Comment créer Unboxed tableau mutable exemple

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

est-il un moyen de créer un de ces cas:

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

Pour le moment, je stocke tout comme Word8 et je fais la conversion avec (enveloppé) fromEnum/toEnum, mais il ne se sent pas bien. J'ai besoin de rigueur et de déballage parce que j'utilise une grande structure de données (> 1.2Go) en mémoire, et je ne peux pas la charger paresseusement. Si je ne trouve aucune solution, je vais tout ré-implémenter en C++, que je préfère éviter pour mon projet actuel. J'ai posé la question sur #haskell mais je n'ai pas eu de réponse, peut-être que ce n'était pas le bon moment de la journée pour demander.

Répondre

6

La mise en œuvre plus simple que je pouvais penser: il suffit envelopper STUArray/IOUArray opérations avec 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 

Maintenant vous pouvez

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

De même, IArray cas pourrait être trivialement écrit aussi bien.

+0

Merci, je n'ai pas pensé à créer un nouveau type pour ça, c'est une bonne façon de le faire. –

1

La création d'une instance pour MArray IOUarray MyType IO devrait être possible. Jetez un oeil à la source de la déclaration d'instance pour MArray IOUarray Bool IO.

Puisque Bool est une instance de Enum et Bounded (et pas beaucoup d'autre), ils utilisent probablement des fonctions de ces classes lors de la création de l'instance.

Vous devrez peut-être dériver Bounded mais ce n'est probablement pas un problème puisque les tableaux non-boxed peuvent contenir uniquement des éléments de taille fixe.

Edit:

Dans this article on peut lire

Vous pouvez même mettre en œuvre vous-même des tableaux unboxed pour d'autres types simples, y compris énumérations.

Questions connexes