Error “No instance for (Num [t])” in Collatz function

五迷三道 提交于 2019-12-20 02:06:43

问题


I am new to Haskell, and programming in general. I am trying to define a function which generates the sequence of Collatz numbers from n. I have:

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)

When I run this in GHCi, I get the error:

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

I don't know what this means. The problem seems to be appending "1" to the list. This problem emerges because

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

generates an infinite sequence of "1"s following the correct Collatz sequence; however,

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

generates all Collatz numbers from n except "1". What am I doing wrong?


回答1:


ony's answer is correct, but since you're new to Haskell, maybe this is a clearer explanation. The : operator prepends a value to a list, so doing somelist : 7 is invalid since that's trying to append a value to a list. That's why (collatz' n) : 1 doesn't compile, since the type of (collatz' n) is a list of numbers.

Try replacing the : 1 with ++ [1].




回答2:


(:) :: a -> [a] -> [a]
Your first line collatz n = (collatz' n) : 1 forces 1 to become [a].
I guess you wanted something like (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 or something like that else you have collatz''' 7 = 7




回答3:


Another way to go at the problem may be for you to use a Data.Sequence structure instead of a list. Sequences allow you to "snoc" a value (put a value on the back of a sequence) as well as the more usual "cons" (put it on the front of the sequence).

Another solution for you may be to use span to make your own "takeUntil" function.

Let me explain: span p xs gives you the same answer as (takeWhile p xs, dropWhile p xs) for whichever p function and xs list you'd use, the same way that splitAt n xs is the same as (take n xs, drop n xs).

Anyway, you can use span to make your own "takeUntil" function:

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

This is the form that you were looking for, when you used the collatz n = (collatz' n) : 1 form.

I hope this helps.



来源:https://stackoverflow.com/questions/3163718/error-no-instance-for-num-t-in-collatz-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!