GHC не запам'ятовує функції.
Однак він обчислює будь-який заданий вираз у коді не більше одного разу на час, коли вводиться його оточуюча лямбда-вираз або, максимум, коли-небудь коли-небудь, якщо він знаходиться на верхньому рівні. Визначення того, де знаходяться лямбда-вирази, може бути дещо складним, коли ви використовуєте синтаксичний цукор, як у вашому прикладі, тому давайте перетворимо їх у еквівалентний синтаксис зневоднення:
m1' = (!!) (filter odd [1..]) -- NB: See below!
m2' = \n -> (!!) (filter odd [1..]) n
(Примітка. Звіт Haskell 98 насправді описує лівий розділ оператора, (a %)як еквівалент \b -> (%) a b, але GHC приєднує його (%) a. Це технічно різні, тому що їх можна розрізнити seq. Я думаю, що я міг би подати квиток GHC Trac про це.)
Враховуючи це, ви можете бачити це в m1'виразіfilter odd [1..] не міститься в жодному лямбда-виразі, тому він буде обчислюватися лише один раз на запуск вашої програми, в той час як в m2', filter odd [1..]буде обчислюватися кожен раз, коли вводиться лямбда-вираз, тобто, на кожен дзвінок о m2'. Це пояснює різницю в термінах, які ви бачите.
Насправді, деякі версії GHC, з певними варіантами оптимізації, матимуть більше значень, ніж зазначено вище в описі. Це може бути проблематично в деяких ситуаціях. Наприклад, розглянемо функцію
f = \x -> let y = [1..30000000] in foldl' (+) 0 (y ++ [x])
GHC може помітити, що yне залежить від цьогоx переписання функції
f = let y = [1..30000000] in \x -> foldl' (+) 0 (y ++ [x])
У цьому випадку нова версія набагато менш ефективна, оскільки їй доведеться зчитувати близько 1 Гб пам'яті, де yвона зберігається, тоді як оригінальна версія працюватиме в постійному просторі і вміщуватиметься в кеш-пам'яті процесора. Насправді в GHC 6.12.1 функція fмайже вдвічі швидша при компіляції без оптимізації, ніж при компіляції -O2.
seqm1 10000000). Існує різниця, хоча, коли не вказано прапор оптимізації. І обидва варіанти вашого "f" мають, до речі, максимальну резидентність 5356 байтів, незалежно від оптимізації (з меншим загальним розподілом, коли використовується -O2).