1

我需要一个程序来检查所有元素对之间的差异是否在 -2 到 2 的区间内( >= -2 && < 2)。如果是,则返回True,否则返回False。例如,[1,2,3]True,但是[1,3,4]False。我正在使用该all功能。我的if条款有什么问题?

allfunc (x : xs)
   = if all (...) xs
      then allfunc xs
      else [x] ++ allfunc xs
allfunc _
   = []

或者我做错了什么?

4

5 回答 5

3

为此,使用列表推导式或 do-notation 可能更容易。

pairsOf lst = do 
  x <- lst
  y <- lst
  return (x, y)

pairsOf返回输入中的数字对列表lst。例如,pairsOf [1,2,3]结果为[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]

现在,您可以定义单行中的一对之间的差异,\(x, y) -> x - y并将其映射到列表中:

differences lst = map (\(x, y) -> x - y) (pairsOf lst)

现在你只需要确保每个元素都在和differences lst之间。-22

当然,这只是一种可能的方法。还有很多其他的方法。

于 2012-06-12T17:16:48.223 回答
2

做你所描述的天真的方法是:

allfunc xs = all (<=2) [abs(a-b) | a <- xs, b <- xs ]

但是,更有效的方法是比较列表的最小值和最大值:

fastfunc [] = true
fastfunc xs = maximum xs - minimum xs <= 2
于 2012-06-13T19:54:53.653 回答
1

为什么不简单...

allfunc xs = (maximum xs - minimum xs) <= 2

或者如果你真的想调查每一对,你可以使用单子:

import Control.Monad
allfunc xs = all ((<=2).abs) $ liftM2 (-) xs xs

liftA2fromControl.Applicative也可以。

于 2012-06-13T15:37:16.353 回答
0

好吧,问题规范不是很清楚。

你说:

所有元素之间的差异在 -2 到 2 的区间内 ( >= -2 && < 2)

但是也:

例如,[1,2,3] 为真,但 [1,3,4] 为假

[1,2,3] 是如何成立的?

假设你的意思是-2 <= diff <= 2,那么我会使用这个:

allfunc :: (Ord a, Num a) => [a] -> Bool
allfunc theList = all (\x -> (x >= -2) && (x<2)) [x-y | x <- theList, y <- theList ]

allfunc [1,2,3] -- => True
allfunc [1,3,4] -- => False
于 2012-06-12T18:10:47.107 回答
-1

基本上,是的,你做错了什么。all旨在采用谓词和要测试的值列表。True因此,当且仅当应用于给定谓词函数时所有值都为真时,它将返回。IE:

allValuesEven = all even
allValuesOdd  = all odd
于 2012-06-12T17:17:45.713 回答