2011-06-05 8 views
9

Aprender Haskell y quieren una función para generar una rejilla 2D similar a cómo lo harían en C:generación de una cuadrícula 2D en Haskell

int data[3][3] 

lo que es un enfoque aceptable y elegante? ¿Cremallera? Foldl?

pude declarar una como:

x = [[0,0,0], 
    [0,0,0], 
    [0,0,0]] 

Pero me gustaría una función con parámetros x e y. Luchando por comprender la forma más fácil y sin for/while :(

+1

¿Qué quiere decir con "generar"? – vicvicvic

+1

@ Cyclone: ​​¿Cómo se ven los bucles for/while en Haskell? – Gabe

+0

@Gabe: Imagino algo como http://www.xoltar.org/old_site/2003//sep/09/haskellLoops.html – Cyclone

Respuesta

18

Parece que se está preguntando "¿qué debo usar en lugar de Arrays en Haskell", ¿verdad? Usted preguntó sobre el uso de listas, que ciertamente no son matrices y deben evitarse para cualquier trabajo serio que requiera acceso no secuencial (por ejemplo, las listas otorgan acceso al elemento O (n) en lugar de O (1)).

Los paquetes que debe considerar: matriz (antiguas, matrices Haskell estándar), vector (nueva, utiliza fusión de secuencia, rápida, una API que es razonable, en caja o sin caja, pero solo una dimensión a menos que las anide), y repa (solo funciona en las versiones más nuevas de GHC, pero permite matrices multidimensionales y operaciones paralelas incluso en representaciones sin caja).

La forma más fácil de inicializar cualquiera de estos (supongo que quiere decir "inicializar" cuando dice "generar") es sus respectivas funciones "fromList". Por ejemplo:

import Data.Vector as V 
... 
    V.fromList $ map V.fromList [[01,02,03],[11,12,13],[22,22,23]] 
+1

¡Puntos justos, TomMD! En cierto modo, me opongo al término "trabajo serio": el rendimiento crítico es una mejor descripción en mi humilde opinión. – vicvicvic

+1

vicvicvic: Correcto, simplemente he editado esa parte para llamar mejor que me refiero a un acceso no secuencial crítico para el rendimiento. –

3

que haría uso de una lista de listas (:: [[a]]), posiblemente con algún tipo nuevo para asegurarse de que todas las listas que tienen la misma longitud.

Para crear una lista que contiene los valores n, puede utilizar replicate :: Int -> a -> [a], de modo de generar una lista de listas, usted acaba de reproducir la lista de nuevo ...

grid :: Int -> Int -> a -> [[a]] 
grid x y = replicate y . replicate x 

Aquí, el parámetro a le permite generar listas con cualquier valor "cero" de cualquier tipo. Se puede usar así:

> grid 3 3 0 
[[0,0,0],[0,0,0],[0,0,0]] 
> grid 2 3 False 
[[False,False],[False,False],[False,False]] 

EDIT: Este sistema de coordenadas utiliza (y, x) me di cuenta (que estaba pensando en (row, column)). Puede cambiar la xey en grid para obtener el sistema "habitual".

+0

Las listas son un reemplazo muy pobre para las matrices. A menos que esté seguro de que no tendrá ningún problema de rendimiento, Dominic consideraría una estructura de datos diferente con acceso O (1). –

+0

Wow eso es muy elegante. Gracias. ¡Ahora para entender replicar! –

+0

@TomdMD.Bien, aunque el rendimiento no es crítico, prefiero no utilizar una solución ingenua cuando existen mejores. Se verá en Data.Vector –

3

Si usted quiere tener algo que no es demasiado complicado con lee rápido y "actualizaciones" razonables rápidas, se debe considerar el uso de un Map (import Data.Map) con (x,y) pares como claves. Agregue funciones auxiliares para verificaciones de rango y para devolver valores predeterminados para entradas faltantes, y tiene un buen reemplazo (siempre que la matriz no sea grande)

Cuestiones relacionadas