Algo así como mapm, pero para las matrices? (Como arrayMap, pero el mapeo de una función impuro)
Pregunta
veo que puedo asignar una función sobre matrices mutables con mapArray, pero no parece ser algo así como mapm (y mapM_). mapArray no me deja imprimir sus elementos, por ejemplo:
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!
El resultado será:
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
¿Hay algo por el estilo en Haskell (o en GHC incluso si no es estándar Haskell)?
Además, he encontrado ninguna función foldr / foldl para las matrices (mutables o no). ¿Existen?
Muchas gracias!
Solución
Tal vez utilizar una de las otras bibliotecas de la matriz, si está haciendo una gran cantidad de mutación? Al igual que uvector?
Si no,
forM_ [1..n] \$ \i ->. unsafeWrite x i
debería estar bien.
Otros consejos
Importar el módulo Data.Traversable. Se define una clase de tipos de justo lo que desea con las instancias ya definidos para la gama y todo tipo de cosas. Se ha generalizado versiones de secuencia y mapm, además de algunas funciones aún más general de que es probable que no se moleste con mucha frecuencia.
Sólo un simple
import Data.Traversable as T
T.mapM doIOStuff arr
funciona bien.
En el ejemplo de la impresión de todos los elementos:. Puede utilizar "mapM_ print . elems
"
Pero parece que desea crear una nueva matriz en donde cada valor es el resultado de una acción monádica de la anterior? En ese caso:
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