Haskell中的惯用向量代数

Haskell中的惯用向量代数,haskell,Haskell,作为在Haskell中使用向量库的一种实践方式,我正在尝试重写我以前用C编写的Nelder-Mead最小化算法。 到目前为止,我在习惯性地翻译一些向量运算时遇到了一些困难 例如,考虑一个函数,它从N + 1的列表中找到N个向量的重心(过滤掉一个索引), 在C语言中,这可以写成 static void get_形心(双**s,int n,int iz, 双倍(C) { 对于(int i=0;iInt->[a]”和“Int->[a]->[a]”,找到了drop (索引Vector,所以搜索“Int-

作为在Haskell中使用向量库的一种实践方式,我正在尝试重写我以前用C编写的Nelder-Mead最小化算法。 到目前为止,我在习惯性地翻译一些向量运算时遇到了一些困难

例如,考虑一个函数,它从N + 1的列表中找到N个向量的重心(过滤掉一个索引),

在C语言中,这可以写成

static void get_形心(双**s,int n,int iz,
双倍(C)
{
对于(int i=0;i
我试着把这个翻译成Haskell,结果是

导入数据.Vector
导入符合条件的数据。向量为V
类型节点=向量双精度
单纯形类型=向量节点
质心::单纯形->整数->节点
质心s iz=V.map(/(从整数$V.length s))$V.zipWith(-)V(s!iz)
其中v=v.foldl转到v.empty s
其中a b=V.zipWith(+)a b
我觉得这段代码很不雅观,因为它没有抓住正在发生的向量代数的本质(而且由于我在加和减s[iz])


一种解决方案是实现某种向量空间类型类或使用更具体的线性代数库,但由于这些都是常见的操作,我想知道是否有更惯用的“直接”解决方案;更具体的图书馆几乎肯定会更干净、更高效

但是,如果您正在寻找的是
centroid
函数的更惯用的实现,我喜欢这个:

centroid' :: Simplex -> Int -> Node
centroid' s iz = let t = foldl1 (V.zipWith (+)) (V.drop iz s)
                     n = fromIntegral (V.length t - 1)
                 in V.map (/ n) t
对您的版本的一个一般性评论是:创建“只写”Haskell代码非常容易。第一行中有太多的内容,很难解析。您的
where
块是朝着正确的方向迈出的一步,但我会更进一步地分解概念组件

也。我不知道有一个函数
drop
,但我知道如果它存在,它需要一个
Int
和一个
向量
到一个新的
向量
。Hoogle不为Vector编制索引,但Vector的API与列表的API非常相似。我搜索了“[a]->Int->[a]”和“Int->[a]->[a]”,找到了
drop


(索引
Vector
,所以搜索“Int->Vector a->Vector a”在那里有效)

为什么要使用
Data.Vector
?一个更具体的图书馆几乎肯定是一条路要走。但是如果你想用这些向量试试,你应该1。切换到“未绑定”版本以获得速度和2。查看矢量切片操作以跳过行/列。谢谢!这就是我一直在寻找的答案。我认为foldl和map抓住了每个向量运算的本质,我可以想象这如何推广到更复杂的算法。