不知道从哪里开始可变向量 [英] Don't know where to start with mutable Vectors

查看:96
本文介绍了不知道从哪里开始可变向量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Data.Vector.*包在Haskell中执行类似的操作,但我真的不知道从哪里开始.我是Haskell的新手,对某些核心概念不甚了解(但我要到达那里).

I am trying to do something like this in Haskell using the Data.Vector.* packages, and I really have no idea where to start. I'm a newb to Haskell, with a tenuous grasp of certain core concepts (but I'm getting there).

我要执行的操作大致可以由以下C代码表示:

What I'm trying to do can be expressed approximately by the following C code:

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];

注意事项:

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

我们将不胜感激您提供的任何帮助.

Any help that you might offer would be greatly appreciated.

推荐答案

这是一个愚蠢的任务

执行C到Haskell的直接转换是很愚蠢的.我之前已经完成过付费工作,但进展并不顺利或很快.最好用目标语言的惯用方式来描述任务并执行它.通过提供该算法的英文描述,您更有可能获得高质量的答案.

It's rather silly to perform direct translation of C to Haskell. I've done it for pay before and it doesn't go smoothly or quickly. It is much better to describe the task and implement it in an idiomatic style in the target language. You would be more likely to get quality answers by providing an English description of the algorithm.

请发布可编译代码

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

When you post questions, please be sure it compiles!

不学习Haskell,如何在Haskell中编写C

用不同语言完成工作的方式可能会发生巨大变化,尤其是当您跨越了从命​​令式到功能性,从可变到不可变,从严格到惰性,从隐式转换到显式或手动管理的内存到垃圾回收等鸿沟时.您正在克服所有这些鸿沟.

How things are done in different languages can vary drastically, especially when you cross a divide such as from imperative to functional, or mutable to immutable, or strict to lazy, or implicit casting to explicit, or manually managed memory to garbage collected. You are crossing all these divides.

如果您的任务是学习Haskell,那么您的起点是错误的.如果您的任务是学习Haskell中的可变向量/数组,那么您需要了解更多基本知识才能体会细微差别.如果您的任务是嘲笑Haskell对数组的支持不佳,那么在Roman出现并制作Vector包之前,您会度过一个非常轻松的时光-这是我的说法:不要看Haskell Array s只看Vector s.

If your task is to learn Haskell, you are starting at the wrong point. If your task is to learn mutable vectors/arrays in Haskell then you need to know more of the fundamentals to appreciate the nuances. If your task is to taunt Haskell for having poor support of arrays then you would have had a really easy time of it before Roman came along and made the Vector package - this is my way of saying: don't look at Haskell Arrays only look at Vectors.

好的,好的,什么解决方案?

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

We'll use the Vector package for our Arrays and the ST monad for mutable operations (your first bullet point):

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

您的主函数采用两个向量并返回一个浮点数.我们首先使用thaw获取对数组的可变引用,并使用简单的折叠使我们能够翻转数组引用.

Your main function takes two vectors and returns a float. We start by obtaining mutable references to the arrays using thaw and use a simple fold to allow us to flip our array references.

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中.它只是从 数组并写入一个新值.它必须在一个元组中返回两个数组.元组在每次迭代时都会翻转,以获得与可变指针相同的语义(第二点):

The inner for loop is contained in op. It just performs some simple reads from the arrays and writes a new value. It has to return the two arrays in a tuple; the tuple is flipped on every iteration to obtain the same semantics of your mutable pointers (your second point):

 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)

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

Consistent with your third point, the inner loop bound changes based on the outter loop.

为了编译可运行的程序,我们将包含main:

Just so we can compile a runable program we'll include main:

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

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

这仅用于教育目的.我还没有测试过,它在道德上应该与您的C相同,但可能会一圈掉或者有其他琐碎的差异.

This is for educational purposes only. I haven't tested this, it should be morally the same as your C but might be off by one in a loop or have other trivial differences.

这篇关于不知道从哪里开始可变向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆