Haskell

时间:2017-07-22 21:55:53

标签: haskell

我想写一个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应该有qposition = [3.0, 3.0, 3.0]u

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

position = [-12.0, -12.0, -12.0]

我尝试过使用Mutable Vectors但尝试将这些包含在我的数据结构中失败了,因为我对Haskell的理解太基础了,我甚至不确定这种方法是否有意义。

有没有简单的方法可以做到这一点?

1 个答案:

答案 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

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