Вопрос

I am currently working on Project Euler for fun, and use Haskell for practicing. However, I encountered a problem, and I cannot seem to produce a smaller example, so here are the codes (for project euler 232):

buildNum (x, y) = multNum x y 1 []
  where multNum num mul exp s = if (num > 10 ^ 100) then s else multNum nNum mul nexp ns
          where next = (num * mul) `div` exp
                ns = num:s
                top = next `mod` 10
                nexp = exp * 10
                nNum = num + nexp * top

sumBuild (x, y) = (head (buildNum (x, y))) * length (buildNum (x, y))

Please ignore bad style here:)

If I load this and run sumBuild(7, 5) here, I would get a exception:

*** Exception: Prelude.head: empty list

But if I change sumBuild to:

sumBuild (x, y) = head (buildNum (x, y))

or

sumBuild (x, y) = length (buildNum (x, y))

then it runs fine.

This is really confusing for me, since there is no side effect and two runs produce different results (at least it seems to be such a case). What is the problem here?

If someone could edit this program into a minimum working example, then I am really grateful!

Thanks for any help!

Это было полезно?

Решение

This is the hint:

> :t sumBuild
sumBuild :: (Int, Int) -> Int
> let a = 7 :: Int
> a > 10^100
True

As a suggestion try always explicitly state types of top level declarations. This helps to avoid such bugs.

Другие советы

The problem is that by multiplying with the result of length, which is an Int, you force all the calculations to be done with the machine-sized Int type, leading to overflows. When you remove that, the default arbitrary-sized Integer type is used instead.

If you add a type signature and a fromIntegral to force the calculations to be done with Integer, everything works as expected.

buildNum :: (Integer, Integer) -> [Integer]
buildNum (x, y) = -- same as before

sumBuild :: (Integer, Integer) -> Integer
sumBuild (x, y) = (head (buildNum (x, y))) * fromIntegral (length (buildNum (x, y)))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top