Haskell中的成对列表修改

Haskell中的成对列表修改,haskell,Haskell,我想编写一个modifyList函数,它获取数据结构列表,使用函数modify修改它们,然后返回修改后的列表。 我遇到的问题是,我的modify函数从列表中获取成对的元素,并将更改应用于这两个元素 这是迄今为止我的(简化)代码: import qualified Data.Vector as V import Data.List data Structure = Structure{ factor :: Double , position :

我想编写一个
modifyList
函数,它获取数据结构列表,使用函数
modify
修改它们,然后返回修改后的列表。 我遇到的问题是,我的
modify
函数从列表中获取成对的元素,并将更改应用于这两个元素

这是迄今为止我的(简化)代码:

import qualified Data.Vector as V
import Data.List

data Structure = Structure{ factor :: Double
                          , position :: V.Vector Double
                          } deriving (Show)

-- Calculates a factor with values from both structures
calculateFactor :: (Structure, Structure) -> Double
calculateFactor (p, q) = (factor p) + (factor q) -- This calculation is simplified     

modify :: (Structure, Structure) -> (Structure, Structure)
modify (a, b) = ( a { position = V.map (+ structureFactor) (position a) }
                , b { position = V.map (subtract structureFactor) (position b) })
            where structureFactor = calculateFactor(a,b)

modifyList :: [Structure] -> [Structure]
modifyList l = [ ??? | (p, q) <- (map (modify) pairs)] -- What do I need to do here?
             where pairs = [(x, y) | (x:ys) <- tails l, y <- ys]
现在,
modifyList list
应该为我列表中的每个元素对调用
modify
(p,q)(p,u)(q,u)
,它给出了一个对的结果列表:

[(Structure {factor = 2.0, position = [6.0,6.0,6.0]}, -- Modified p
  Structure {factor = 3.0, position = [-4.0,-4.0,-4.0]}), -- Modified q
  (Structure {factor = 2.0, position = [7.0,7.0,7.0]}, -- Also modified p
  Structure {factor = 4.0, position = [-5.0,-5.0,-5.0]}), -- Modified u
  (Structure {factor = 3.0, position = [8.0,8.0,8.0]}, -- Also q
  Structure {factor = 4.0, position = [-6.0,-6.0,-6.0]})] -- Also u
但是我实际上想要得到的是与
[p,q,u]
相同的列表,其中
p
具有
位置=[12.0,12.0,12.0]
就像我手动调用
p'=fst(modify(p,q))
然后调用
p=fst(modify(p',u))
为原始
位置p
提供一个新值。分别
q
应具有
位置=[3.0,3.0,3.0]
u
位置=[-12.0,-12.0,-12.0]

命令式语言的伪代码可能如下所示:

p = Structure 2 (V.replicate 3 1.0)
q = Structure 3 (V.replicate 3 1.0)
u = Structure 4 (V.replicate 3 1.0)
list = [p, q, u]
Structure = {Double factor, Vector position};
Structure[] list = {p, q, u};
for i = 0; i < list.length; i++;
    for j = i+1; j < list.length; j++;
        structureFactor = calculateFactor(list[i], list[j]);
        //Destructive updates
        list[i].position += structureFactor; //Add factor to each vector value
        list[j].position -= structureFactor;
Structure={双因子,向量位置};
结构[]列表={p,q,u};
对于i=0;i
我尝试过使用可变向量进行实验,但未能将其包含在我的数据结构中,因为我对Haskell的理解太基础了,我甚至不确定这种方法是否有意义


有什么简单的方法可以做到这一点吗?

好的,我想这就是您想要做的:为列表中的每一对元素创建一个函数(与列表中的顺序相同),对该对元素求值一些修改函数,然后将结果放回原来的位置

mapPairs :: ((a,a)->(a,a)) -> [a] -> [a]
mapPairs f [] = []
mapPairs f (x:xs) = s : mapPairs f res where
  rec a [] = (a,[])
  rec a (y:ys) = let (b,c) = f (a,y)
                     (a',l') = rec b ys in
    (a',c:l')
  (s,res) = rec x xs
我想这是可行的,但我手头没有电脑。然而,似乎您可能想要一个不同的解决方案。无论如何,下面是如何编写
modifyList

modifyList = mapPairs modify
以下是实际解决您的问题的尝试:

postFactors' [] = []
postFactors' (x:xs) = case postFactors' xs of
  [] -> factor x : [0]
  a:as -> (factor x + a) : a : as
postFactors = tail . postFactors'
preFactors = scanl (+) 0 . map factor
addPos v f = v {position = V.map (+f) $ position v}
modifyList l = zipWith (-) (postFactors l) (preFactors l) & zipWith addPos l

描述:从列表中每个元素之前/之后的所有内容中查找因子的总和。然后找出他们的差异。然后将其添加到每个元素的位置

这里确实不清楚您想要什么。您说要调用
modify
生成一个新列表。例如,在
[p,q,u]
案例中,您希望实际结果列表是什么?因为您只是列出了一组函数调用,而没有描述如何组合它们。啊,是的,也许我应该用更好的措辞,我希望我的
modifyList
函数使用我的
modify
函数生成一个修改过的列表。下面的示例只是为了说明
modifyList
应该做什么,以及我的问题是什么。我仍然不明白您试图做什么。请添加一个简单的例子,例如一些数字修改功能。是的,我也很难理解目标。我同意一个更简单的例子,你可以展示一些示例输入和预期输出,这可能有助于澄清问题。很难理解你想要什么:你的第一个列表理解基本上是一个
map
,但你可能需要一些折叠(
foldr
?)或一些map变体,比如
mapacuml/mapacumr
。您始终可以使用显式递归。谢谢您的回答,不幸的是,这两个代码段都不能单独工作。我修复了第二个问题,删除了带有addPos l的
&zipWith
,它为每个结构提供了一个总因子列表,这几乎就是我想要的。唯一的问题是,我实际上需要调用modify来找出我的因子是什么,因为它取决于我的结构中的各种变量。我认为第一个代码片段可能会成功,但我无法修复错误:。也许你可以用一些在线编译器来修复它,比如?很抱歉。我在手机上写下了这些答案,手上没有Haskell植入装置,所以我并不奇怪它们没有编译。我可能要离开电脑甚至手机三周,所以我恐怕无法纠正这些问题。第二个版本仅适用于您的描述,其中对位置的修改仅取决于之前和之后的因子之和。如果修改不影响factor,那么如果factor被更复杂的函数替换,这应该仍然有效。我对第一个版本做了一些修改,但它可能不会修复任何可能存在的类型错误。要自己解决这个问题,您需要解决如何以更实用的方式表达您的算法,而不是试图将一系列强制性的非交换更新方法硬塞进HaskellUpdate中:可能已经修复了映射对定义中的笨拙类型错误。Ghc表示,它适用于太少的论点。它适用于太少的论点