2009-06-10 12 views
10

digamos que tengo del tipo siguiente:
Cómo crear unboxed instancia de matriz mutable

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

¿Hay una manera de crear uno de estos casos:

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

Para el momento en que almacenar todo como Word8 y yo hacemos la conversión con (wrapped) fromEnum/toEnum, pero no se siente bien. Necesito rigurosidad y unboxing porque estoy usando una gran estructura de datos (> 1.2Go) en la memoria, y no puedo cargarla perezosamente. Si no encuentro ninguna solución, voy a volver a implementar todo en C++, que prefiero evitar para mi proyecto actual.

He hecho la pregunta sobre #haskell pero no recibí respuesta, tal vez no era el mejor momento para preguntar.

Respuesta

6

La implementación más simple que podía pensar: simplemente envolver STUArray/IOUArray operaciones 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 

Ahora puede

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

Del mismo modo, IArray casos podrían ser trivialmente escrito también.

+0

Gracias, no pensé en crear un nuevo tipo para esto, es una buena manera de hacerlo. –

1

Hacer una instancia para MArray IOUarray MyType IO debería ser posible. Eche un vistazo a la fuente de la declaración de instancia para MArray IOUarray Bool IO.

Dado que Bool es una instancia de Enum y Bounded (y no mucho más) probablemente utilicen funciones de esas clases al hacer la instancia.

Es posible que deba derivar Bounded, pero probablemente no sea un problema, ya que las matrices no compartidas solo pueden contener elementos de tamaño fijo.

Editar:

En this artículo uno puede leer

Incluso puede aplicar matrices unboxed mismo para otros tipos simples, incluyendo las enumeraciones.

Cuestiones relacionadas