Andy Melnikov (nponeccop) wrote,
Andy Melnikov
nponeccop

Category:

Двухминутка ненависти

Функциональные языки окружены неким ореолом славы. Дескать, благодаря чистоте возможно выполнять архисложные оптимизации, благодаря которым можно писать код левой ногой, а компилятор как-нибудь соптимизирует в tight loop. Вот и сегодня наткнулся на такой радостный пассаж в 8.2. Unboxed types and primitive operations:
GHC is built on a raft of primitive data types and operations. While you really can use this stuff to write fast code, we generally find it a lot less painful, and more satisfying in the long run, to use higher-level language features and libraries. With any luck, the code you write will be optimised to the efficient unboxed version in any case. And if it isn't, we'd like to know about it.
Выглядит так, как будто можно забыть о деталях и довериться компилятору. Хрен вам! Вот мой любимый prodx в своей наивной ипостаси:
module Main where

prodx a b = foldl (*) b a

main = print $ prodx [2..4] 5
Казалось бы, должно фьюзиться, и компилироваться в нечто такое:
int a = 5;
for (int i = 2; i <= 4; i ++)
{
   a *= i;
}

printf("%d\n", a);
Казалось бы, цикл из 3-4 инструкций, а то и просто вычисленная на этапе компиляции константа. Но не тут-то было! Авторы Хаскеля нашли миллион вполне легитимных причин, по которым эти 2 строчки должны компилироваться в хуйню.

Для начала 3 загадки фанатам Хаскеля:
  1. Какой тип имеет [2..4]?
  2. Фьюзится ли foldl и [2..4] и почему?
  3. Почему main = print $ foldr (+) 1 [1..1000000] приводит к stack overflow?
Subscribe

  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 39 comments