3

我是 Haskell 的新手,一般来说是编程。我正在尝试定义一个从n生成 Collat​​z 数字序列的函数。我有:

collatz n = (collatz' n) : 1
   where collatz' n = (takeWhile (>1) (collatz'' n))
          where collatz'' n = n : collatz'' (collatz''' n)
                 where collatz''' 1 = 1
                       collatz''' n = if (even n) then (div n 2) else ((3*2)+1)

当我在 GHCi 中运行它时,我得到了错误:

No instance for (Num [t])
  arising from the literal `2' at <interactive>:1:7
Possible fix: add an instance declaration for (Num [t])

我不知道这是什么意思。问题似乎是将“1”附加到列表中。出现这个问题是因为

collatz' n = (takeWhile (>0) (collatz'' n))

在正确的 Collat​​z 序列之后生成无限的“1”序列;然而,

collatz' n = (takeWhile (>1) (collatz'' n))

从n中生成除 "1" 之外的所有 Collat​​z 数。我究竟做错了什么?

4

3 回答 3

6

(:) :: a -> [a] -> [a]
你的第一线collatz n = (collatz' n) : 1力量1成为[a]
我猜你想要类似(collatz' n) ++ [1]
And you have error in if (even n) then (div n 2) else ((3*2)+1)there should be((3*n)+1或类似的东西collatz''' 7 = 7

于 2010-07-02T06:45:42.340 回答
5

ony 的答案是正确的,但是由于您是 Haskell 的新手,也许这是一个更清晰的解释。:运算符值附加到列表中,因此这样做somelist : 7是无效的,因为它试图将附加到列表中。这就是为什么(collatz' n) : 1不编译,因为类型(collatz' n)是数字列表。

尝试将 替换: 1++ [1]

于 2010-07-02T06:51:39.957 回答
0

另一种解决问题的方法可能是让您使用 Data.Sequence 结构而不是列表。序列允许你“snoc”一个值(把一个值放在序列的后面)以及更常见的“缺点”(把它放在序列的前面)。

您的另一个解决方案可能是使用span您自己的“takeUntil”功能。

让我解释一下:为您提供与您将使用的任何函数和列表span p xs相同的答案,与.(takeWhile p xs, dropWhile p xs)pxssplitAt n xs(take n xs, drop n xs)

无论如何,您可以使用span自己的“takeUntil”功能:

takeUntil p xs = taken ++ take 1 dropped where
                 (taken, dropped) = span p xs

这是您在使用表单时要查找的collatz n = (collatz' n) : 1表单。

我希望这有帮助。

于 2010-07-02T18:17:23.443 回答