Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm Haskell递归-查找列表中数字之间的最大差异_Algorithm_Haskell_Recursion - Fatal编程技术网

Algorithm Haskell递归-查找列表中数字之间的最大差异

Algorithm Haskell递归-查找列表中数字之间的最大差异,algorithm,haskell,recursion,Algorithm,Haskell,Recursion,现在的问题是:我需要使用递归找到列表中相邻数字之间的最大差异。以下面的列表为例:[1,2,5,6,7,9]。两个相邻数字之间的最大差值为3(介于2和5之间) 我知道递归可能不是最好的解决方案,但我正在努力提高在Haskell中使用递归的能力 以下是我当前拥有的代码: largestDiff (x:y:xs) = if (length (y:xs) > 1) then max((x-y), largestDiff (y:xs)) else 0 基本上-列表将持续变短,直到达到1(即,无法比

现在的问题是:我需要使用递归找到列表中相邻数字之间的最大差异。以下面的列表为例:[1,2,5,6,7,9]。两个相邻数字之间的最大差值为3(介于2和5之间)

我知道递归可能不是最好的解决方案,但我正在努力提高在Haskell中使用递归的能力

以下是我当前拥有的代码:

largestDiff (x:y:xs) = if (length (y:xs) > 1) then max((x-y), largestDiff (y:xs)) else 0
基本上-列表将持续变短,直到达到1(即,无法比较更多的数字,然后返回0)。当0向上传递调用堆栈时,max函数随后用于实现“山中之王”类型的算法。最后-在调用堆栈的末尾,应该返回最大的数字

问题是,我的代码中出现了一个无法解决的错误:

Occurs check: cannot construct the infinite type:
  t1 = (t0, t1) -> (t0, t1)
In the return type of a call of `largestDiff'
Probable cause: `largestDiff' is applied to too few arguments
In the expression: largestDiff (y : xs)
In the first argument of `max', namely
  `((x - y), largestDiff (y : xs))'
有人有一些智慧的话可以分享吗

谢谢你的时间

编辑:感谢大家抽出时间-经过多次尝试和错误,我最终独立发现了一种更简单的方法

largestDiff [] = error "List too small"
largestDiff [x] = error "List too small"
largestDiff [x,y] = abs(x-y)
largestDiff (x:y:xs) = max(abs(x-y)) (largestDiff (y:xs))

再次感谢大家

因此,代码抛出错误的原因是

max((x-y), largestDiff (y:xs))
在Haskell中,不要在参数周围使用括号并用逗号分隔,正确的语法是

max (x - y) (largestDiff (y:xs))
您使用的语法被解析为

max ((x - y), largestDiff (y:xs))
看起来您正在将一个元组传递给
max

然而,这并不能解决问题。我总是得到
0
回复。相反,我建议将问题分解为两个函数。要计算最大差值,请先编写一个函数来计算差值,然后编写一个函数来计算最大差值:

diffs :: Num a => [a] -> [a]
diffs [] = []                            -- No elements case
diffs [x] = []                           -- One element case
diffs (x:y:xs) = y - x : diffs (y:xs)    -- Two or more elements case

largestDiff :: (Ord a, Num a) => [a] -> a
largestDiff xs = maximum $ map abs $ diffs xs
注意我是如何将递归拉到最简单的情况中的。在遍历列表时,我们不需要计算最大值;这是可能的,只是更复杂而已。因为Haskell有一个方便的内置函数,可以为我们计算列表的最大值,所以我们也可以利用它。我们的递归函数简洁明了,然后将其与
maximum
组合,以实现所需的
largestDiff
。仅供参考,
diff
实际上只是一个计算数字列表导数的函数,对于数据处理来说,它可能是一个非常有用的函数


编辑:需要对
largestDiff
进行
Ord
约束,并在计算最大值之前添加到
map abs

因此,代码抛出错误的原因是

max((x-y), largestDiff (y:xs))
在Haskell中,不要在参数周围使用括号并用逗号分隔,正确的语法是

max (x - y) (largestDiff (y:xs))
您使用的语法被解析为

max ((x - y), largestDiff (y:xs))
看起来您正在将一个元组传递给
max

然而,这并不能解决问题。我总是得到
0
回复。相反,我建议将问题分解为两个函数。要计算最大差值,请先编写一个函数来计算差值,然后编写一个函数来计算最大差值:

diffs :: Num a => [a] -> [a]
diffs [] = []                            -- No elements case
diffs [x] = []                           -- One element case
diffs (x:y:xs) = y - x : diffs (y:xs)    -- Two or more elements case

largestDiff :: (Ord a, Num a) => [a] -> a
largestDiff xs = maximum $ map abs $ diffs xs
注意我是如何将递归拉到最简单的情况中的。在遍历列表时,我们不需要计算最大值;这是可能的,只是更复杂而已。因为Haskell有一个方便的内置函数,可以为我们计算列表的最大值,所以我们也可以利用它。我们的递归函数简洁明了,然后将其与
maximum
组合,以实现所需的
largestDiff
。仅供参考,
diff
实际上只是一个计算数字列表导数的函数,对于数据处理来说,它可能是一个非常有用的函数

编辑:需要对
largestDiff
进行
Ord
约束,并在计算最大值之前添加到
map abs

以下是我的看法

首先是一些助手:

diff a b = abs(a-b)
pick a b = if a > b then a else b
然后,解决方案是:

mdiff :: [Int] -> Int
mdiff [] = 0
mdiff [_] = 0
mdiff (a:b:xs) = pick (diff a b) (mdiff (b:xs))
您必须提供两个结束子句,因为序列可能包含偶数或奇数个元素。

我的看法是这样的

首先是一些助手:

diff a b = abs(a-b)
pick a b = if a > b then a else b
然后,解决方案是:

mdiff :: [Int] -> Int
mdiff [] = 0
mdiff [_] = 0
mdiff (a:b:xs) = pick (diff a b) (mdiff (b:xs))

您必须提供两个结束子句,因为序列可能包含偶数或奇数个元素。

可以获得此问题的另一个解决方案,它可以避免您的错误 只需变换列表并折叠/缩小它们

import Data.List (foldl')

diffs :: (Num a) => [a] -> [a]
diffs x = zipWith (-) x (drop 1 x)

absMax :: (Ord a, Num a) => [a] -> a
absMax x = foldl' max (fromInteger 0) (map abs x)
现在我承认这对于初学者来说有点难,所以我将解释上面的内容。 函数
zipWith
使用二进制函数转换两个给定列表, 在本例中为
(-

我们传递给
zipWith
的第二个列表是
drop1x
,这只是另一种方法 描述列表的尾部,但是
tail[]
会导致错误,
drop 1[]
只生成空列表。因此
drop 1
是“更安全”的选择

因此,第一个函数计算相邻的差值

第二个函数的名称表明它计算最大绝对值 给定列表的值(仅部分为真),如果传递 空列表

但这是如何发生的,从右到左阅读,我们看到
map abs
将每个列表元素转换为其绝对值,该值由
Num a
约束。然后
foldl'
-函数遍历列表并 累加上一个累加器和当前元素的最大值 列表遍历。此外,我想指出,
foldl'
是“严格的”
foldl
-函数的姐妹/兄弟,后者很少使用, 因为它倾向于建立一组称为thunks的未赋值表达式

所以,让我们停止这些废话,看看它的实际行动;-)

>设a=diff[1..3]:[Int]
>>>zipWith(-)[1,2,3](下降1[1,2,3])
zipWith(-)[1,2,3][2,3]
[1-2,2-3]——zipWith在en处停止