This is an old revision of the document!
Întârzierea evaluării
Moduri de evaluare a unei expresii:
- evaluare aplicativă - argumentele funcțiilor sunt evaluate înaintea aplicării funcției asupra lor.
- evaluare lenesa - întârzie evaluarea parametrilor până în momentul când aceasta este folosită efectiv.
Evaluare aplicativă vs. evaluare normală
Fie urmatoarea expresie, scrisă într-o variantă relaxată a Calculului Lambda (în care valori numerice și operații pe acestea sunt permise, iar funcțiile sunt în formă uncurried):
(λx.λy.(x + y) 1 2)
Evident, în urma aplicării funcției de mai sus, expresia se va evalua la 3. Să observăm, însă, cazul în care parametrii funcției reprezintă aplicații de funcții:
(λx.λy.(x + y) 1 (λz.(z + 2) 3))
Desigur, evaluarea expresiei (λz.(z + 2) 3)
va genera valoarea 5
, de unde deducem că rezultatul final al expresiei va fi 6
( adunarea lui 1 cu rezultatul anterior ). În cadrul acestui raționament, am presupus că parametrii sunt evaluați înaintea aplicării funcției asupra acestora. Vom vedea, în cele ce urmează, că evaluarea se poate realiza și in alt mod.
Evaluare aplicativă
Evaluarea aplicativă (eager evaluation) este cea în care fiecare expresie este evaluată imediat. În exemplul de mai sus, evaluarea aplicativă va decurge astfel:
(λx.λy.(x + y) 1 (λz.(z + 2) 3)) (λx.λy.(x + y) 1 5) 6
Evaluare normală
Spre deosebire de evaluarea aplicativă, evaluarea normală va întarzia evaluarea unei expresii, până când aceasta este folosită efectiv. Exemplu:
(λx.λy.(x + y) 1 (λz.(z + 2) 3)) (1 + (λz.(z + 2) 3)) (1 + 5) 6
Exerciții:
I. Streams
1. construiți șirul numerelor naturale
2. construiți șirul numerelor pare (puteți să va folosiți de șirul definit anterior)
3. construiți șirul Fibonacci (în testele automate, șirul începe cu 1, 1, 2, 3, 5, 8, ...
)
II. Aproximații numerice
1. definiți funcția build :: (a -> a) -> a -> [a]
care primește un generator g
și o valoare inițială a0
și generează lista: [a0, g a0, g (g a0), g (g (g a0)), ... ]
iterate
, deja existentă în Haskell.Prelude> :t iterate iterate :: (a -> a) -> a -> [a]
2. definiți funcția select
care primește o toleranță $ e$ și o listă $ l$ și întoarce elementul $ l_n$ care satisface proprietatea: $ abs(l_n - l_{n+1}) < e$
3. Rădăcină pătrată
Fiind dat un număr $ k$ , am vrea să găsim o aproximare numerică a $ \sqrt{k}$ . Fie șirul:
$ a_{n+1} = \frac{1}{2}(a_n + \frac{k}{a_n})$
Știm că $ \displaystyle \lim_{n \rightarrow \infty} a_n = \sqrt{k}$
a) Scrieți o funcție care calculează $ \sqrt{k}$ cu toleranța 0.01
, exploatând faptul că șirul: $ a_n = 1/2(a_{n-1} + k/a_{n-1})$ converge către $ \sqrt{k}$ când n
tinde la infinit.
4. Aproximație pentru derivata unei funcții f
într-un punct a
:
a) Scrieți o funcție care generează lista: [h_0, h_0/2, h_0/4, h_0/8, …]
b) Scrieți o funcție care calculează lista aproximarilor lui f'(a)
, calculate astfel: $ \displaystyle f'(a)=\lim_{h \rightarrow 0} \frac{f(a+h)-f(a)}{h}$
c) Scrieți o funcție care calculează derivata in a
a unei funcții f
, cu toleranța 0.01
5. Aproximație pentru integrala unei funcții pe intervalul [a,b]
:
a) Scrieți o funcție care aproximează valoarea integralei unei funcții f
între a
și b
, cu toleranța 0.01
. Strategia de îmbunătățire a unei aproximări constă în spargerea intervalului [a,b]
în două sub-intervale de dimensiune egală [a,m]
si [m,b]
, calculul integralei pe fiecare, și adunarea rezultatului.