1
listX n = xs
if sum[x | x <- [2, 4..n-1], y <- [1..n-1], y `rem` x == 0] == y
    then insert y xs
    else return ()

Alright, first time trying to work with Haskell, and only having novice Java knowledge has led to some problems. What I was trying to do, was to define the result of the function listX n as a list called xs. My idea was that the program would grab every number of from 1 to n, and check if it was equal to the sum of its positive divisors. Clearly, I have failed horribly and need help, pointers to concepts I haven't understood is extremely appreciated.

  • Try to give your function a type. If you don't know Haskell types (yet), what would be the type of the Java function? `static int[] listX(int)`? Also, try to figure out what `listX` should return. What should `listX` return on `1`? What should `listX` return on `2`? This can already give you some grasps how to implement `listX` later. – Zeta Oct 06 '15 at 13:34

1 Answers1

3

Your main problem seems to be that you still think imperative (with the insert) - also () is the value unit - you probably wanted to write [] (the empty list) instead - but still the xs here is totally undefined so you would have to fix this too (and I don't see how to be honest).

perfect numbers

I think I can see a basic idea in there, and I think the best way to fix this is to go full list-comprehension (as you seem to understand them quite well) - here is a version that should work:

listX n = [ x | x <- [1..n], sum [ y | y <- [1..x-1], x `mod` y == 0] == x]

As you can see I changed this a bit - first I check all x from 1 to n if they could be perfect - and I do this by checking by summing up all proper divisors and checking if the sum is equal to x (that's the job of the sum [...] == x part) - in case you don't know this works because you can add guards to list comprehensions (the sum [..] == x filters out all values of x where this is true).

a nicer version

to make this a bit more readable (and separate the concerns) I would suggest writing it that way:

properDivisors :: Integer -> [Integer]
properDivisors n = [ d | d <- [1..n-1], n `mod` d == 0]

isPerfect :: Integer -> Bool
isPerfect n = sum (properDivisors n) == n

perfectNumbers :: [Integer]
perfectNumbers = filter isPerfect [1..]

perfectNumbersUpTo :: Integer -> [Integer]
perfectNumbersUpTo n = takeWhile (<= n) perfectNumbers
Random Dev
  • 51,810
  • 9
  • 92
  • 119