2009-09-29 16 views
1

Je vois que je peux mapper une fonction sur des tableaux mutables avec mapArray, mais il ne semble pas y avoir quelque chose comme mapM (et mapM_). mapArray ne me laisse pas imprimer ses éléments, par exemple:Quelque chose comme mapM, mais pour les tableaux? (comme arrayMap, mais mappage d'une fonction impure)

import Data.Array.Storable 

arr <- newArray (1,10) 42 :: IO -- answer to Life, Universe and Everything 
x <- readLn :: IO Int 
mapArray (putStrLn.show) arr -- <== this doesn't work! 

Le résultat sera:

No instances for (MArray StorableArray Int m, 
        MArray StorableArray (IO()) m) 
    arising from a use of `mapArray' at <interactive>:1:0-27 
Possible fix: 
    add an instance declaration for 
    (MArray StorableArray Int m, MArray StorableArray (IO()) m) 
In the expression: mapArray (putStrLn . show) arr 
In the definition of `it': it = mapArray (putStrLn . show) arr 

Y at-il quelque chose comme ça dans Haskell (ou GHC même si Haskell pas standard)?

De plus, je n'ai trouvé aucune fonction foldr/foldl pour les tableaux (mutables ou non). Est-ce qu'ils existent?

Merci beaucoup!

Répondre

3

Peut-être utiliser l'une des autres bibliothèques de matrices, si vous faites beaucoup de mutation? Comme uvector?

Sinon,

forM_ [1..n] \$ \i ->. unsafeWrite x i 

devrait être bon.

+0

Merci beaucoup! forM_ [1..10 :: Int] $ (\ i -> readArray arr i >> = putStrLn.show) fonctionne pour putStrLn (et devrait fonctionner pour d'autres fonctions impures). uvector semble très agréable. Recommanderiez-vous uvector ou StorableArrays si je veux appeler les fonctions C via FFI en code critique de vitesse? – Jay

+3

"si je veux appeler les fonctions C via FFI en code critique de vitesse?" --- alors vous devez utiliser des tableaux étrangers ou stockables, car ils sont épinglés en mémoire. –

2

Pour l'exemple d'impression de tous les éléments: vous pouvez utiliser "mapM_ print . elems".

Mais il semble que vous vouliez créer un nouveau tableau où chaque valeur est le résultat d'une action monadique de la précédente? Dans ce cas:

arrayMapM :: (Monad m, Ix i) => (a -> m b) -> Array i a -> m (Array i b) 
arrayMapM func src = 
    liftM (listArray (bounds src)) . mapM func . elems $ src 
+0

Merci - mais cela semble fonctionner pour Arrays, et non pour StorerArrays. (Je voudrais interface avec C, passant le pointeur de tableau, donc je préfère utiliser StorableArrays) – Jay

+0

@Jay: voulez-vous changer les valeurs du tableau en place? ne pas en créer un nouveau? – yairchu

+0

@yairchu: oui. Le tableau devrait être mutable et je dois le passer à C fonctions externes. Il y a aussi un problème de performance. – Jay

5

Importez le module Data.Traversable. Il définit une classe de type pour ce que vous voulez avec les instances déjà définies pour le tableau et toutes sortes de choses. Il a des versions généralisées de séquence et mapM, ainsi que des fonctions encore plus générales que vous ne vous soucierez probablement pas très souvent.

Juste un

simple,
import Data.Traversable as T 

T.mapM doIOStuff arr 

fonctionne très bien.