保存并传递先前结果的映射

And*_*rey 3 haskell map

当在Haskell中通过三对角矩阵算法求解线性方程组时,我遇到了以下问题.

我们有三个载体:a,bc,我们想使第三矢量c'是它们的组合:

c'[i] = c[i] / b[i], i = 0
c'[i] = c[i] / (b[i] - a[i] * c'[i-1]), 0 < i < n - 1
c'[i] = undefined, i = n - 1

在Haskell中实现上面的公式如下:

calcC' a b c = Data.Vector.generate n f
  where
    n = Data.Vector.length a
    f i = 
      | i == 0 = c!0 / b!0 
      | i == n - 1 = 0
      | otherwise = c!i / (b!i - a!i * f (i - 1))

看起来这个函数由于重复而calcC'具有复杂度O(n 2).但我们所需要的只是通过f先前生成的值向内部函数传递一个参数.

我编写了我自己的generate复杂度O(n)和辅助函数的版本mapP:

mapP f xs = mapP' xs Nothing
  where
    mapP' [] _ = []
    mapP' (x:xs) xp = xn : mapP' xs (Just xn)
      where
        xn = f x xp

generateP n f = Data.Vector.fromList $ mapP f [0 .. n-1]

可以看出,mapP行为类似于标准map,但也传递给先前生成的值或Nothing第一次调用的映射函数.

我的问题:在Haskell中有没有相当标准的方法可以做到这一点?我不是要重新发明吗?

谢谢.

Hei*_*mus 10

有两种称为标准功能mapAccumLmapAccumR该做的正是你想要的.

mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
Run Code Online (Sandbox Code Playgroud)

基本上,他们表现得像组合foldmap.

map   f   = snd . mapAccumL (\_ x -> (()   , f x) ()
foldl f b = fst . mapAccumL (\b x -> (f b x, () ) b
Run Code Online (Sandbox Code Playgroud)