[Haskell筆記]let/in語句

復合函數有助於避免重復。比如,我們有一個求一元二次方程的函數(假定方程有實根):

roots a b c =
    ((-b + sqrt(b*b - 4*a*c)) / (2*a),
     (-b - sqrt(b*b - 4*a*c)) / (2*a))

sqrt(b*b - 4*a*c)重復出現了,使得整個定義顯得很冗長。我們可以利用復合函數來改善這個情況:

delta a b c = sqrt(b*b - 4*a*c)
roots' a b u =
  ((-b + u) / (2*a),
   (-b - u) / (2*a))
roots a b c = roots' a b (delta a b c)

不過,這種情況,使用let/in語句能使代碼更緊湊:

roots a b c =
    let delta = sqrt (b*b - 4*a*c)
    in  ((-b + delta) / (2*a),
         (-b - delta) / (2*a))

使用let/in還有一個好處,就是let語句中定義的符號,如上例的delta,只在in語句後有用。也就是說,定義的delta只在roots函數內部有用。其它函數看不到roots內部定義的delta。當程序比較大時,這種局部綁定可以有效避免符號雜亂的情況。

練習

16.1 下面是一個輸出一元二次函數與x軸交點及頂點坐標的函數,試補全之:

f a b c =
  let delta = sqrt (b*b - 4*a*c)
      v =
  in  [(v + delta / (2*a),0),
      (                  ,0),
      (v,delta/(-4*a))]

答案

15.1

vol s h = s * h
areaCircle r = pi * r ^ 2
areaRect a b = a * b
Prelude> volCircle = vol (areaCircle r) h
Prelude> volRect = vol (areaRect a b) h

Leave a Reply