我必须创建一个名为difference的函数,在这个函数中,我用zipWith计算每一对的差异,并将其放入一个列表中。
例如,differences [1..5] == [1, 1, 1, 1]。
所以[2-1, 3-2, 4-3, 5-4] == [1, 1, 1, 1]。
我想列一张元组的清单,如下所示:
[1..5] = [(1,2), (2,3), (3,4), (4,5)]然后像这样使用列表组合:
[zipWith (-) a b | a <- y, b <- x]其中x是元组的第一个元素,y是第二个元素。
函数类型为differences :: Num a => [a] -> [a]。
发布于 2019-04-20 23:04:38
您就快到了--但是zipWith本身返回一个列表,所以您不希望将其放入列表理解中,除非您希望结果是列表列表(这里不需要)。
zipWith (-)在这里绝对是正确的主意-它需要2个列表,并给出一个新的列表,通过取给定列表的对应元素之间的差异。在这种情况下,您的输出列表比一个输入列表要短一个元素,您希望在两个列表上使用zipWith (-),这些列表包括:
所以你要找的函数是:
differences xs = zipWith (-) (tail xs) (init xs)请注意,这并不理想,因为如果init和tail都是空的,那么xs和xs都会导致运行时出错。如果您将空列表呈现给此函数(尽管您可能会认为没有空列表,因为您将从一个单例列表中获得一个空列表),则输出空列表是有意义的,因此您可以通过模式匹配来定义函数以显式地迎合空列表,从而避免运行时崩溃:
differences [] = []
differences xs = zipWith (-) (tail xs) (init xs)虽然我个人认为这很好,而且非常明确,但实际上并不需要同时使用init和tail --如果给出长度不等的列表,zipWith工作得很好,因为它只会将较大的列表缩小到大小。因此,differences xs = zipWith (-) (tail xs) xs是一个可行的、稍微简单一些的替代方案。
发布于 2019-04-20 23:43:09
在罗宾·齐格蒙德的回答的基础上,函数的Applicative实例在这里工作得很好:
(f <*> g) xs == f xs (g xs)所以
differences = zipWith subtract <*> tail(其中subtract = flip (-).)
发布于 2019-04-22 02:20:02
正如4卡斯尔所暗示的,在-less解中使用drop 1而不是tail,意味着我们可以省略[]的情况,如drop 1 [] = [] (与tail []不同,tail []会导致运行时错误):
differences xs = zipWith (-) (drop 1 xs) xs为了与这个没有显式模式解构的解决方案形成对比,我将提到使用init、tail和drop的任何拼写。
differences xs@(_:ys) = zipWith (-) ys xshttps://stackoverflow.com/questions/55778450
复制相似问题