GHC tidak mengotori fungsi.
Namun, ia menghitung setiap ekspresi yang diberikan dalam kode paling banyak sekali setiap kali ekspresi lambda di sekitarnya dimasukkan, atau paling banyak sekali jika berada di level teratas. Menentukan di mana ekspresi lambda bisa menjadi sedikit rumit saat Anda menggunakan gula sintaksis seperti dalam contoh Anda, jadi mari kita ubah ini menjadi sintaks desugared yang setara:
m1' = (!!) (filter odd [1..]) -- NB: See below!
m2' = \n -> (!!) (filter odd [1..]) n
(Catatan: Laporan Haskell 98 sebenarnya menjelaskan bagian operator kiri seperti yang (a %)
setara dengan \b -> (%) a b
, tetapi GHC mendeskripsikannya (%) a
. Ini secara teknis berbeda karena dapat dibedakan oleh seq
. Saya rasa saya mungkin telah mengirimkan tiket GHC Trac tentang hal ini.)
Diberikan ini, Anda dapat melihat bahwa di m1'
, ekspresi filter odd [1..]
tidak terdapat dalam ekspresi lambda, jadi itu hanya akan dihitung sekali per jalannya program Anda, sementara di m2'
, filter odd [1..]
akan dihitung setiap kali ekspresi lambda dimasukkan, yaitu, pada setiap panggilan m2'
. Itu menjelaskan perbedaan waktu yang Anda lihat.
Sebenarnya, beberapa versi GHC, dengan opsi pengoptimalan tertentu, akan berbagi lebih banyak nilai daripada yang ditunjukkan oleh uraian di atas. Ini bisa menjadi masalah dalam beberapa situasi. Misalnya, perhatikan fungsinya
f = \x -> let y = [1..30000000] in foldl' (+) 0 (y ++ [x])
GHC mungkin memperhatikan bahwa y
tidak bergantung pada x
dan menulis ulang fungsi ke
f = let y = [1..30000000] in \x -> foldl' (+) 0 (y ++ [x])
Dalam hal ini, versi baru jauh kurang efisien karena harus membaca sekitar 1 GB dari memori tempat y
disimpan, sedangkan versi asli akan berjalan dalam ruang konstan dan masuk ke dalam cache prosesor. Faktanya, di bawah GHC 6.12.1, fungsinya f
hampir dua kali lebih cepat saat dikompilasi tanpa pengoptimalan daripada saat dikompilasi -O2
.
seq
m1 10000000). Namun ada perbedaan ketika tidak ada tanda pengoptimalan yang ditentukan. Dan kedua varian "f" Anda memiliki residensi maksimum 5356 byte terlepas dari pengoptimalannya (dengan alokasi total yang lebih sedikit ketika -O2 digunakan).