8

我试图在 Haskell 中使用 Data.Vector.* 包做这样的事情,我真的不知道从哪里开始。我是 Haskell 的新手,对某些核心概念了解甚少(但我已经到了那里)。

我正在尝试做的事情可以用以下C代码大致表达:

float *arrA = /* initialized to array of length n */;
float *arrB = /* initialized to array of length n */;
for (i = 1; i < n; i++) {
  for (j = 0; j < n - i; j++) {
    arrB[j] = someFn(i, j, arrA[j], arrB[j+1])
  }
  float *p = arrA;
  arrA = arrB;
  arrB = p;
}
return arrA[0];

注意事项:

  • 出于性能原因重用数组,但我需要其中两个以避免践踏下一次迭代所需的值
  • 数组被交换
  • 内循环的上限随着外循环的每次迭代而变化

您可能提供的任何帮助将不胜感激。

4

1 回答 1

20

这是一个愚蠢的任务

将 C 直接翻译成 Haskell 是相当愚蠢的。我以前做过付费,但进展并不顺利或迅速。最好用目标语言以惯用的方式描述任务并实现它。通过提供算法的英文描述,您更有可能获得高质量的答案。

请发布可编译代码

当您发布问题时,请确保它可以编译!

学习 Haskell 而不是如何在 Haskell 中编写 C

不同语言的处理方式可能会有很大差异,尤其是当您跨越诸如从命令式到函数式,或从可变到不可变,或从严格到惰性,或隐式转换为显式或手动管理的内存到垃圾收集的鸿沟时。你正在跨越所有这些鸿沟。

如果您的任务是学习 Haskell,那么您的起点就错了。如果您的任务是在 Haskell 中学习可变向量/数组,那么您需要了解更多的基础知识以了解其中的细微差别。如果你的任务是嘲笑 Haskell 对数组的支持很差,那么在 Roman 出现并制作 Vector 包之前,你会很轻松地度过它——这就是我的说法:不要只看 HaskellArray的外观在Vectors。

好的好的,有什么解决办法?

我们将把Vector包用于我们的数组,将STmonad 用于可变操作(你的第一个要点):

import qualified Data.Vector.Unboxed.Mutable as M
import qualified Data.Vector.Unboxed as V
import Control.Monad.ST
import Control.Monad

您的 main 函数接受两个向量并返回一个浮点数。我们首先使用获取对数组的可变引用,thaw并使用简单的折叠来允许我们翻转数组引用。

someFunc :: V.Vector Float -> V.Vector Float -> Float
someFunc arrA arrB = runST $ do
        -- Obtain mutable copies of the arrays
        mA <- V.thaw arrA 
        mB <- V.thaw arrB
        (mA', mB') <- foldM op (mA, mB) [1..n-1] -- for(i = 1 ; i < n; i++)
        M.read mA' 0
 where
 n = min (V.length arrA) (V.length arrB)

内部 for 循环包含在op. 它只是从数组中执行一些简单的读取并写入一个新值。它必须在一个元组中返回两个数组;每次迭代都会翻转元组以获得可变指针的相同语义(您的第二点):

 op (mA, mB) i = do
        forM_ [0..n-i-1] $ \j -> do
                v1 <- M.read mA j
                v2 <- M.read mB (j+1)
                M.write mB j (someFn i j v1 v2)
        return (mB, mA)

与您的第三点一致,内循环边界会根据外循环而变化。

这样我们就可以编译一个可运行的程序,我们将包括 main:

someFn i j f1 f2 = f1 + fromIntegral i + fromIntegral j - f2

main = print $ someFunc (V.fromList [1..10]) (V.fromList [0..9])

这仅用于教育目的。我没有对此进行测试,它在道德上应该与您的 C 相同,但可能会在循环中偏离一个或有其他微不足道的差异。

于 2012-07-14T03:20:33.447 回答