При выполнении измерений времени всегда компилируйте;ghci предназначен для быстрого цикла изменения-восстановления-запуска, а не для быстрого выполнения созданного кода.Однако даже после следования этому совету между вашими фрагментами есть огромная разница во времени.
Ключевое различие между вашим Java и Haskell заключается в использовании sqrt вместо деления на 2. Ваши оригиналы на моей машине:
% javac Test.java && echo 10000 | /usr/bin/time java Test >/dev/null
0.21user 0.02system 0:00.13elapsed 186%CPU (0avgtext+0avgdata 38584maxresident)k
0inputs+0outputs (0major+5823minor)pagefaults 0swaps
% ghc -O2 test && echo 10000 | /usr/bin/time ./test >/dev/null
8.85user 0.00system 0:08.87elapsed 99%CPU (0avgtext+0avgdata 4668maxresident)k
0inputs+0outputs (0major+430minor)pagefaults 0swaps
Так 0,2 с для Java, 8,9 с для Haskell.После перехода к использованию квадратного корня со следующим изменением:
- primeNumber x = primNumberRec x (div x 2)
+ primeNumber x = primNumberRec x (ceiling (sqrt (fromIntegral x)))
я получаю следующий тайминг для Haskell:
% ghc -O2 test && echo 10000 | /usr/bin/time ./test >/dev/null
0.07user 0.00system 0:00.07elapsed 98%CPU (0avgtext+0avgdata 4560maxresident)k
0inputs+0outputs (0major+427minor)pagefaults 0swaps
Теперь в 3 раза быстрее, чем код Java.(И, конечно, есть значительно лучшие алгоритмы, которые сделают его еще быстрее.)