我正在尝试使用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];
注意事项:
非常感谢您提供的任何帮助。
答案 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相同,但可能会在一个循环中关闭或者有其他微不足道的差异。