iT邦幫忙

2023 iThome 鐵人賽

DAY 12
0
Software Development

Haskell 從入門到放棄系列 第 12

[Haskell 從入門到放棄] Day 12 - lazy…evaluation…

  • 分享至 

  • xImage
  •  

今天要來介紹一個在 FP 中相當常見的特性 lazy evaluation (惰性求值) ,簡單來說就是當需要值的時候才會真正把值計算出來。

lazy evaluation

我們先來想一個問題,這段程式碼會走訪幾次這個 List?

map (^2) $ map (^2) $ [1..10] 

按照我們直覺應該會想我先 map 一次產生 [1,4,9,16,25,36,49,64,81,100] 然後再 map 變成結果

[1,16,81,256,625,1296,2401,4096,6561,10000]

但這個答案是「只會走訪一次」,這歸功於 lazy evaluation 這個特性,因為這是在走訪到個別元素時才會真正使用 map 裡的 expression 去計算出值。

那 lazy evaluation的好處是什麼?當然顯而易見就是這樣**「效能比較好」**畢竟只走訪一次,但對我來說更大的好處是也連帶的讓我們不必為了效能而去讓很多複雜運算 map 刻意放在同一個 map 裡,我覺得這點對可讀性幫助很大,在寫 JS 時總會為了減少 map 次數而講每次 map 裡的 function 愈寫愈大,而在 Haskell 裡這就不會是問題了。

無限 List

lazy evaluation 是也非常適合來操作無限 List

take 1000 $ map (^2) $ [1..]

這是一個對於一個無限List中的每個元素都平方,最後只取前一千個元素的 expression ,在沒有 lazy evaluation 我們根本達不到這件事情。因為既然是無限 List 那根本沒有執行完的一天,但在 Haskell 我們可以用 taketakeWhile 甚至是 head 、pattern matching 等等你想得到可以對 List 操作的方法來處理無限 List(當然 tail 就沒辦法了xD)

take 10 $ filter (>1000) [1..] -- [1001,1002,1003,1004,1005,1006,1007,1008,1009,1010]
takeWhile (<= 1000) $ map (^3) [2,4..] -- [8,64,216,512,1000]
[1..] !! 3000 -- 3001
head $ map (^2) $ map (+2) $ map (+2) [1..] -- 25

今天寫得十分的趕QQ

但希望有成功的把 lazy evaluation 介紹到一個程度


上一篇
[Haskell 從入門到放棄] Day 11 - 繼續談 higher order function
下一篇
[Haskell 從入門到放棄] Day13 - Tuple
系列文
Haskell 從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言