不知道从哪里开始使用可变向量

时间:2012-07-13 20:58:08

标签: haskell

我正在尝试使用Data.Vector。*包在Haskell中做这样的事情,我真的不知道从哪里开始。我是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];

注意事项:

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

非常感谢您提供的任何帮助。

1 个答案:

答案 0 :(得分:20)

这是一个愚蠢的任务

将C直接翻译为Haskell是相当愚蠢的。我以前做过付费而且不顺利或很快。描述任务并以目标语言的惯用风格实现它要好得多。通过提供算法的英文描述,您将更有可能获得高质量的答案。

请发布可编辑代码

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

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

如何在不同的语言中完成任务可能会有很大的不同,特别是当你跨越鸿沟时,例如从命令到功能,或者可变到不可变,或者从严格到懒惰,或者隐式转换为显式,或手动管理的内存到垃圾收集。你正在跨越所有这些分歧。

如果您的任务是学习Haskell,那么您将从错误的角度出发。如果您的任务是在Haskell中学习可变向量/数组,那么您需要了解更多基础知识才能理解细微差别。如果你的任务是嘲讽Haskell对阵列的支持不足那么你就可以在Roman出现之前有一个非常简单的时间来制作Vector包 - 这是我的说法:不要看Haskell {{1只看Array s。

好的,解决方案是什么?

我们将使用Vector包用于我们的数组和Vector monad用于可变操作(您的第一个要点):

ST

你的main函数接受两个向量并返回一个浮点数。我们首先使用import qualified Data.Vector.Unboxed.Mutable as M import qualified Data.Vector.Unboxed as V import Control.Monad.ST import Control.Monad 获取对数组的可变引用,并使用简单的折叠来允许我们翻转数组引用。

thaw

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

op

与第三点一致,内部循环绑定基于外部循环而变化。

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

 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)

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