2010-10-17 6 views
5

À des fins de mise en cache, je souhaite créer un tableau qui mappe les valeurs d'entrée de la fonction pour afficher les valeurs. Je sais que ma fonction ne sera utilisée que dans cette gamme spécifique, je pense à quelque chose comme ceci:Comment créer une matrice Haskell à partir d'une fonction

MyType = ... deriving (Ix) 

myFunction :: MyType -> foo 

myCache = createArrayFromFunction (start,end) myFunction 

Est-ce possible ou que je pense juste « ne fonctionne pas » et il est une autre solution. J'ai besoin de tableaux, car j'ai besoin de l'accès O (1) aux membres et je connais la longueur depuis le début.

+0

Ceci est entièrement fonctionnel (et je le fais assez souvent). En fait, vous pouvez définir une fonction 'createArrayFromFunction' pour que votre code fonctionne. –

Répondre

6

Si vous voulez juste créer un cache, vous pouvez simplement utiliser listArray et map, aussi longtemps que vous avez une liste de tous vos indices:

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

Je suppose que MyType a un Enum exemple ici; Si ce n'est pas le cas, vous aurez besoin d'un autre moyen pour générer une liste d'entrées valides, qui dépend de votre type. Comme l'a souligné Reid Barton, c'est ce que vise range.

Une autre option, si vous souhaitez présenter une fonction à l'utilisateur, serait

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 !) 

alors vous ne pas exporter myInternalFunc de votre module; vous n'exporteriez probablement pas non plus myFuncCache, mais je pourrais imaginer en avoir besoin. Si vous n'êtes pas dans un module, vous pouvez mettre myInternalFunc dans un let - ou where -block dans myFuncCache. Une fois que vous faites cela, myFunction mt fait juste une recherche de cache, et est ainsi O (1).

+1

Utilisez 'range (start, end)' (http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-Ix.html#v:range), pas ' [début..fin] '. –

+0

@Reid: Merci! Je n'utilise pas beaucoup Arrays. –

+0

La raison est juste, que je sais, que ma fonction ne prend que quelques 500 valeurs d'entrée spécifiques, mais cela prend beaucoup de temps pour calculer les résultats. THX. – fuz

3

Si vous regardez des tableaux, veuillez également considérer Vector. Mis à part la fusion et la puissante fonction d'épissage, une différence importante à noter est que les vecteurs sont tous indexés. En utilisant cette librairie votre fonction de génération est:

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

Le problème est: Je veux quelque chose qui n'est pas indexé. – fuz

+0

Si vous avez un Enum alors ce que vous utilisez est indexé de manière intuitive. En effet, si votre type est une instance de 'Ix' il ne devrait pas être difficile de faire un wrapper autour de Vector pour vos besoins d'indexation. –

Questions connexes