Arrays haskell中是否有一个功能可以像accumArray和foldr一样工作?
让我调用函数AccumArrayArrays haskell中是否有一个功能可以像accumArray和foldr一样工作?,arrays,haskell,fold,Arrays,Haskell,Fold,让我调用函数AccumArray accumrArray :: (e' -> e -> e) An accumulating function -> e A default element -> (i, i) The bounds of the array -> [(i, e')] List of associati
accumrArray ::
(e' -> e -> e) An accumulating function
-> e A default element
-> (i, i) The bounds of the array
-> [(i, e')] List of associations
-> a i e The array
accumrArray (:) [] (1,2) [(1,1),(2,2),(2,3)] === array [(1,[1]), (2,[2,3])]
head $ (accumrArray (:) [] (1,1) [(1,x)|x<-[4..]]) ! 1 === 4
AccumArray::
(e'->e->e)一个累加函数
->e默认元素
->(i,i)数组的界
->[(i,e')]协会名单
->a对数组进行加密
AccumArray(:)[(1,2)[(1,1)、(2,2)、(2,3)]==数组[(1[1]),(2[2,3])]
head$(accurmrray(:)[(1,1)[(1,x)| x不是最有效的,但是。。。
accumArray f x b l=accumArray(翻转f)x b(反向l)
真奇怪……我几天前为其他人编写了此函数。该函数最初出现在LML中(我相信),但从未进入Haskell阵列库
给你:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Array
import System.IO.Unsafe
import Data.IORef
import Data.Array.MArray
import Data.Array.Base
import Control.Monad
import Data.Array.IO
accumArrayR :: forall a e i. Ix i => (a -> e -> e) -> e -> (i,i) -> [(i,a)] -> Array i e
accumArrayR f e bounds@(l,u) assocs = unsafePerformIO $ do
ref <- newIORef assocs
arr <- newArray_ bounds
let _ = arr :: IOArray i e
let n = safeRangeSize (l,u)
let elem x = unsafePerformIO $ do
ass <- readIORef ref
let loop [] = writeIORef ref [] >> return e
loop ((y,a):rest) = do
let ix = safeIndex bounds n y
let r = f a (elem x)
unsafeWrite arr ix r
if (ix == x)
then writeIORef ref rest >> return r
else loop rest
loop ass
forM_ [0..n] $ \ix -> unsafeWrite arr ix (elem ix)
unsafeFreeze arr
{-#语言范围的TypeVariables}
导入数据。数组
导入System.IO不安全
导入数据.IORef
导入Data.Array.MArray
导入Data.Array.Base
进口管制
导入Data.Array.IO
accumArrayR::对于所有a e i.Ix i=>(a->e->e)->e->(i,i)->[(i,a)]->数组i e
accumArrayR f e bounds@(l,u)assocs=未安全性能$do
ref>返回r
埃尔斯环休息
环驴
表格[0..n]$\ix->unsafeWrite arr ix(elem ix)
不安全
读者面临的挑战:使用Accumarayr
实现图形的线性时间深度优先搜索
Edit我应该提到,该函数并不像编写的那样是线程安全的。将IORef
转换为MVar
可以修复它,但可能有更好的方法。我认为
accumrArray f x b l = accumArray (flip f) x b (reverse l)
这确实是最好的解决方案(归功于sclv的答案)
它所谓的“低效”来自这样一个事实,即foldr
从右向左应用函数f
但是,由于accumArray
是严格的,l
永远不能是无限的,否则程序将不正确。它永远不会终止
因此,foldl(flip f)
和foldr
一样好,但它无法处理无限列表(l)通过谷歌搜索lml和accumArray让我看到了1993年的邮件列表历史:我是唯一一个对loop ass
感到惊讶的人吗?