Мой первый опыт программирования был с Haskell. Для моих специальных потребностей мне нужен был инструмент, который был легко освоен, быстр для кодирования и прост в обслуживании, и я могу сказать, что он отлично справился с работой.
Однако в какой-то момент масштаб моих задач стал намного больше, и я подумал, что C может подойти им лучше, и это произошло. Может быть, я не был достаточно опытным с точки зрения [любого] программирования, но я не смог сделать Haskell столь же быстрым, как C, хотя я слышал, что правильный Haskell способен к подобной производительности.
Недавно я подумал, что еще раз попробую Haskell, и хотя он по-прежнему хорош для простых простых (с точки зрения вычисления) задач, он, похоже, не способен сопоставлять скорость C с такими проблемами, как гипотеза Collatz. Я читал:
Сравнение скорости с Project Euler: C против Python против Erlang vs Haskell
Оптимизация GHC: гипотеза Collatz
реализация collatz-list с использованием haskell
Но из того, что я вижу, простые методы оптимизации, в том числе:
- выбор "более жестких" типов, таких как Int64 вместо Integer
- оптимизация GHC на
- с использованием простых методов оптимизации, таких как избегание ненужных вычислений или более простых функций.
все еще не делают код Haskell даже близким к почти идентичному (с точки зрения методологии) коду C для действительно больших чисел. Единственное, что, по-видимому, делает его производительность сопоставимой с C [для крупномасштабных задач], использует методы оптимизации, которые делают код длинным, ужасающим монадическим адом, что противоречит принципам, которые так сильно ценят Haskell (и I).
Здесь версия C:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int32_t col(int64_t n);
int main(int argc, char **argv)
{
int64_t n = atoi(argv[1]), i;
int32_t s, max;
for(i = 2, max = 0; i <= n; ++i)
{
s = col(i);
if(s > max) max = s;
}
printf("%d\n", max);
return 0;
}
int32_t col(int64_t n)
{
int32_t s;
for(s = 0; ; ++s)
{
if(n == 1) break;
n = n % 2 ? 3 * n + 1 : n / 2;
}
return s;
}
и версия Haskell:
module Main where
import System.Environment (getArgs)
import Data.Int (Int32, Int64)
main :: IO ()
main = do
arg <- getArgs
print $ maxCol 0 (read (head arg) :: Int64)
col :: Int64 -> Int32
col x = col' x 0
col' :: Int64 -> Int32 -> Int32
col' 1 n = n
col' x n
| rem x 2 == 0 = col' (quot x 2) (n + 1)
| otherwise = col' (3 * x + 1) (n + 1)
maxCol :: Int32 -> Int64 -> Int32
maxCol maxS 2 = maxS
maxCol maxS n
| s > maxS = maxCol s (n - 1)
| otherwise = maxCol maxS (n - 1)
where s = col n
TL; DR: Является ли код Haskell быстрым для записи и простым в обслуживании только для простых вычислений и теряет эту характеристику, когда производительность имеет решающее значение?