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

bro*_*s94 8 haskell

我试图在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];
Run Code Online (Sandbox Code Playgroud)

注意事项:

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

我们非常感谢您提供的任何帮助.

Tho*_*son 20

这是一个愚蠢的任务

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

请发布Compilable Code

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

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

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

如果您的任务是学习Haskell,那么您就是从错误的角度出发.如果您的任务是在Haskell中学习可变向量/数组,那么您需要了解更多基础知识才能理解细微差别.如果你的任务是嘲讽Haskell对阵列的支持不好那么你就可以在Roman出现之前让它非常容易,并制作了Vector包 - 这是我的说法:不要看Haskell Array的唯一看法在Vectors.

好的,解决方案是什么?

我们将使用Vector我们的Arrays包和STmonad进行可变操作(您的第一个要点):

import qualified Data.Vector.Unboxed.Mutable as M
import qualified Data.Vector.Unboxed as V
import Control.Monad.ST
import Control.Monad
Run Code Online (Sandbox Code Playgroud)

你的main函数需要两个向量并返回一个float.我们首先使用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)
Run Code Online (Sandbox Code Playgroud)

内部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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

main = print $ someFunc (V.fromList [1..10]) (V.fromList [0..9])
Run Code Online (Sandbox Code Playgroud)

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