2009-06-10 5 views
10

powiedzmy mam następujące rodzaje:
Jak stworzyć unboxed zmienny instancji Array

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

Czy istnieje sposób, aby stworzyć jeden z takich przypadków:

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

na chwilę przechowywać wszystko jak Word8 i ja dokonujemy konwersji z (opakowane) zEnum/toEnum, ale to nie jest w porządku. Potrzebuję ścisłości i rozpakowania, ponieważ używam dużej struktury danych (> 1.2Go) w pamięci i nie mogę załadować jej leniwie. Jeśli nie znajdę żadnego rozwiązania, zamierzam ponownie wdrożyć wszystko w C++, którego wolę unikać w przypadku mojego obecnego projektu.

Zadałem pytanie na #haskell, ale nie otrzymałem odpowiedzi, może to nie była dobra pora dnia.

Odpowiedz

6

Najprostsza implementacja mogłem pomyśleć: po prostu owinąć STUArray/IOUArray operacje z 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 

Teraz można

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

Podobnie IArray przypadki mogą być trywialnie jak dobrze napisany.

+0

Dzięki, nie pomyślałem o stworzeniu nowego typu tego, to dobry sposób na zrobienie tego. –

1

Utworzenie instancji dla MArray IOUarray MyType IO powinno być możliwe. Spójrz na źródło dla deklaracji instancji dla MArray IOUarray Bool IO.

Ponieważ Bool jest instancją zarówno Enum, jak i Bounded (i niewiele więcej) prawdopodobnie używają funkcji z tych klas podczas tworzenia instancji.

Być może trzeba będzie wyprowadzić Bounded, ale to prawdopodobnie nie jest problem, ponieważ niezabezpieczone tablice mogą zawierać tylko elementy o stałym rozmiarze.

Edit:

W this artykuł można przeczytać

Można nawet wdrożyć unboxed tablice siebie dla innych typów prostych, takich wyliczeń.