我想写一个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]
如何进行这些修改以便后续函数调用可以使用更新的值?
举个例子,我定义了一些这样的数据:
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]
现在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
position = [12.0, 12.0, 12.0]
,就像我手动调用p' = fst(modify (p, q))
然后调用{{ 1}}给原始p = fst(modify(p', u))
一个新的值。分别position p
应该有q
和position = [3.0, 3.0, 3.0]
,u
。
命令式语言的伪代码可能如下所示:
position = [-12.0, -12.0, -12.0]
我尝试过使用Mutable Vectors但尝试将这些包含在我的数据结构中失败了,因为我对Haskell的理解太基础了,我甚至不确定这种方法是否有意义。
有没有简单的方法可以做到这一点?
答案 0 :(得分:0)
好的我认为这就是你想要做的事情:拥有一个函数,对于列表中的每对元素(按照与列表中相同的顺序),评估该对上的一些修改函数,然后将结果返回他们来自哪里。
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
描述:从列表的每个元素之前/之后的所有内容中查找因子的总和。然后找出他们的差异。然后将其添加到每个元素的位置