像mapM,但对于数组? (像arrayMap,但映射不纯的函数)

时间:2009-09-29 22:22:54

标签: arrays haskell monads

我看到我可以使用mapArray在可变数组上映射函数,但似乎没有像mapM(和mapM_)这样的东西。 mapArray不允许我打印它的元素,例如:

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!

结果将是:

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

在Haskell中是否存在类似的东西(即使不是标准的Haskell,GHC中也是如此)?

另外,我发现数组没有foldr / foldl函数(可变或不可变)。它们存在吗?

非常感谢!

3 个答案:

答案 0 :(得分:5)

导入模块Data.Traversable。它定义了一个类型类,可以为已经为数组和各种事物定义的实例提供所需的类型。它具有序列和mapM的通用版本,以及一些你可能不会经常打扰的更通用的函数。

只是一个简单的

import Data.Traversable as T

T.mapM doIOStuff arr

工作正常。

答案 1 :(得分:3)

如果你做了很多变异,也许使用其他一个数组库?像uvector一样?

否则,

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

应该没问题。

答案 2 :(得分:2)

有关打印所有元素的示例:您可以使用“mapM_ print . elems”。

但听起来你想要创建一个新数组,其中每个值都是前一个monadic动作的结果?在那种情况下:

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