2010-10-17 34 views
5

Para fines de almacenamiento en caché, quiero crear una matriz, que asigna los valores de entrada de la función a los valores de salida. Yo sé, que mi función se utilizará sólo en este rango específico, pienso en algo como esto:Cómo crear una matriz Haskell a partir de una función

MyType = ... deriving (Ix) 

myFunction :: MyType -> foo 

myCache = createArrayFromFunction (start,end) myFunction 

Es esto posible o sólo debo pensar "no funcional" y no hay otra solución. Necesito arreglos, porque necesito O (1) acceso a los miembros y conozco su longitud desde el principio.

+0

Esto es totalmente funcional (y lo hago con bastante frecuencia). De hecho, puede definir una función 'createArrayFromFunction' para que su código funcione. –

Respuesta

6

Si lo que desea es crear una memoria caché, a continuación, puedes utilizar listArray y map, siempre y cuando usted tiene una lista de todos sus índices:

myCache :: Array MyType Foo 
myCache = listArray (start,end) . map myFunction $ range (start,end) 

I asumido que MyType tiene una instancia Enum aquí; si no lo hace, necesitará alguna otra forma de generar una lista de entradas válidas, que depende de su tipo. Como señaló Reid Barton, esto es para lo que range es.

Otra opción, si desea presentar una función para el usuario, sería

myInternalFunc :: MyType -> Foo 
myInternalFunc mt = (complex calculation) (using mt) 

myFuncCache :: Array MyType Foo 
myFuncCache = listArray (start,end) . map myFunction $ range (start,end) 

myFunction :: MyType -> Foo 
myFunction = (myFuncCache !) 

Entonces no habría exportar myInternalFunc de su módulo; probablemente tampoco exporte myFuncCache, pero podría imaginar que lo necesite. Si no se encuentra en un módulo, puede poner myInternalFunc en un let o where -block dentro de myFuncCache. Una vez que haga esto, myFunction mt solo hace una búsqueda en caché, y también lo es O (1).

+1

Use 'rango (inicio, fin)' (http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-Ix.html#v:range), no ' [start..end] '. –

+0

@Reid: ¡Gracias! No uso mucho Arrays. –

+0

La razón es que sé que mi función solo toma unos 500 valores de entrada específicos, pero lleva mucho tiempo calcular los resultados. Gracias. – fuz

3

Si está buscando matrices, también considere Vector. Además de la fusión y la poderosa función de empalme, una diferencia importante que vale la pena señalar es que todos los vectores están indexados. Usando esta biblioteca su función de generación es:

generate :: Int -> (Int -> a) -> Vector a 
+0

El problema es: quiero algo que no esté indexado en Int. – fuz

+0

Si tiene un Enum, entonces lo que está utilizando es IS 'Int' indexado de una manera de hablar. De hecho, si su tipo es una instancia de 'Ix', no debería ser difícil crear un contenedor alrededor de Vector para sus necesidades de indexación. –

Cuestiones relacionadas