Haskell在计算最小值的同时减少所有元素

Haskell decrease all elements while computing minimum

提问人:rik99 提问时间:3/10/2023 更新时间:3/10/2023 访问量:74

问:

我必须编写一个 Haskell 函数,该函数给定一个列表,该函数构造一个新列表,其中包含减少最小值的元素。shiftToZero :: (Num a, Ord a) => [a] -> [a]

该函数不应多次访问列表元素(利用懒惰)。

例如:shiftToZero [5,4,2,6] -> [3,2,0,4]

有什么建议可以解决这个问题吗?

列出 Haskell 懒惰评估

评论

1赞 chepner 3/10/2023
除非这是那些令人费解的“打结”问题之一,否则如果不首先扫描所有元素以找到要从中减去的值,您就无法生成第一个元素。shiftToZero xsxshead xs
0赞 Noughtmare 3/10/2023
您可能对为什么属性语法很重要感兴趣。
2赞 Daniel Wagner 3/10/2023
@chepner 确实有一个令人脑洞大开的结解决方案。
0赞 chi 3/10/2023
请注意,在 Haskell 中,我们可以写出这样的东西,这是一种奇怪的写法。由于懒惰,递归对定义不会发散,而是产生两个值,即使结果的第二个分量依赖于第一个分量。在你的例子中,你可以使用类似的东西,除了在右手边有一个更复杂的表达式。f x = b where (a,b) = (2*x,a+3)f x = 2*x+3(a,b) = ...
0赞 duplode 3/10/2023
相关新闻: 允许查看部分最终结果的变形

答:

1赞 Daniel Wagner 3/10/2023 #1

我会给出一个提示,首先通过一个更简单的问题来解决。我想有一个类型为 .帮助程序应返回与此函数相同的答案:helper :: (Num a, Ord a) => (a, [a]) -> (a, [a])

inefficientHelper (x, xs) = (minimum xs, map (\x' -> x'-x) xs)

问题在于,它在两个单独的传递中计算其两个答案,因此它永远不可能成为我们可以用于实现您关心的功能的组件。因此,您的首要任务是实现以返回正确的值(由此低效实现指定),但同时只对列表进行一次传递。inefficientHelperhelperxs

据推测,这是在一些教材中作为练习提供的,因此最新的教材将有其他打结的例子,可以作为之后的提示。但如果没有,那就用谷歌吧——有很多关于“喜结连理”的文章。