Reputation: 862
I am trying to implement collatz-list using Haskel: Here's my code:
collatz n
| mod n 2 == 0 = div n 2
| otherwise = 3 * n + 1
collatzList n
| n < 1 = error "Cannot have negative number"
collatzList
| n == 1 = [n]
| otherwise = n:collatzList (collatz n)
The error message I am getting is this: parse error on input `collatzList' [1 of 1] Compiling Main ( exer.hs, interpreted ) Failed, modules loaded: none.
Can anyone tell me why I am getting this message?
Upvotes: 2
Views: 2621
Reputation: 8395
Generating a list of values that only depend on the previous value is a typical application for the unfoldr
function (Data.List.unfoldr
):
import Data.List (unfoldr)
collatzList = unfoldr nextCollatz
where nextCollatz n | n <= 0 = Nothing
| n == 1 = Just (1,0)
| even n = Just (n, n `quot` 2)
| otherwise = Just (n, 3*n+1)
unfoldr f x0
takes a starting value x0
, and applies a function f
to it. If f x0
is Nothing
, the algorithm terminates; if it is Just (push, next)
, it adds push
to the result list, and uses next
as the new value for x0
. Another example, generating squares up to 100 using unfoldr:
import Data.List (unfoldr)
squareList = unfoldr pow2
where pow2 n | n > 100 = Nothing
| otherwise = Just (n, 2*n)
-- "Add n to the result list,
-- start next step at 2*n."
(And the obligatory remark about error
: it's usually better to make the function return some dummy value. In my Collatz function above for example, the result for non-positive integers is an empty list instead of an exception.)
Upvotes: 0
Reputation: 139930
I get different errors (using GHC 7.4.1):
> :load "/tmp/C.hs"
[1 of 1] Compiling Main ( /tmp/C.hs, interpreted )
/tmp/C.hs:9:11: Not in scope: `n'
/tmp/C.hs:9:21: Not in scope: `n'
/tmp/C.hs:10:23: Not in scope: `n'
/tmp/C.hs:10:46: Not in scope: `n'
Failed, modules loaded: none.
This is because you forgot the n
argument in your second equation for collatzList
. You can either add this argument
collatzList n
| n < 1 = error "Cannot have negative number"
collatzList n -- the n was missing here
| n == 1 = [n]
| otherwise = n:collatzList (collatz n)
or, since the left hand sides are now the same, you can simply join it with the first one:
collatzList n
| n < 1 = error "Cannot have negative number"
| n == 1 = [n]
| otherwise = n:collatzList (collatz n)
Upvotes: 4
Reputation: 51633
You are redefining collatzList
.
collatzList
| n == 1 = [n]
| otherwise = n:collatzList (collatz n)
do this:
collatz n
| mod n 2 == 0 = div n 2
| otherwise = 3 * n + 1
collatzList n
| n < 1 = error "Cannot have negative number"
| n == 1 = [n]
| otherwise = n:collatzList (collatz n)
Upvotes: 2