2010-07-02 85 views
3

我是Haskell的新手,並且一般編程。我試圖定義一個函數,它可以從n生成Collat​​z數字的序列。我有:錯誤「Collat​​z函數中沒有(Num [t])」的實例

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)) 

Ñ生成除 「1」 在Collat​​z號碼。我究竟做錯了什麼?

回答

5

ONY的答案是正確的,但因爲你是新來的Haskell,也許這是更清楚的解釋。 :運算符將值掛起到列表中,因此somelist : 7無效,因爲它正在嘗試 ap將值掛起到列表中。這就是爲什麼(collatz' n) : 1不能編譯的原因,因爲(collatz' n)的類型是一個數字列表。

嘗試用++ [1]代替: 1

+0

'(collat​​z'n):[]'很好。它會產生類似於[[a]]的東西(實際上原始的例子是編譯的,但是對於第一個參數'a'沒有類型綁定可以滿足類限制:'collat​​z ::(Integral a,Num [[a] ])=> a - > [[a]]')。問題是任何數字(即'1')只能編譯成滿足類「數字a」的數據值。 – ony 2010-07-02 07:01:54

+0

也謝謝:爲了強制(:)工作,我已經重寫了以前的所有函數。你爲我節省了很多時間! – danportin 2010-07-02 07:04:14

6

(:) :: a -> [a] -> [a]
你的第一線collatz n = (collatz' n) : 1軍隊1成爲[a]
我猜你想要的東西,像(collatz' n) ++ [1]
你有錯誤if (even n) then (div n 2) else ((3*2)+1)應該有((3*n)+1或類似的別的東西你有collatz''' 7 = 7

+0

謝謝:這是有道理的,並澄清(:)爲我。 – danportin 2010-07-02 07:02:19

0

解決此問題的另一種方法可能是讓您使用Data.Sequence結構而不是列表。序列允許您「嗅探」一個值(在序列的背面放置一個值)以及更常見的「cons」(將其放在序列的前面)。

您的另一個解決方案可能是使用span來創建您自己的「takeUntil」功能。

讓我解釋一下:span p xs給你相同的答案(takeWhile p xs, dropWhile p xs)無論哪個p功能和xs列表中,您會使用,同樣的方式,splitAt 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表格的形式。

我希望這會有所幫助。