Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
pp:lazylab [2021/04/25 14:59]
pdmatei
pp:lazylab [2021/04/25 17:20] (current)
calin_andrei.bucur
Line 1: Line 1:
 ====== 8. Lazy evaluation ====== ====== 8. Lazy evaluation ======
  
-====== Evaluare leneșă ======+When passing **parameters** to a function, programming language design offers **two options** which are not mutually exclusive (both strategies can be implemented in the language):
  
 +  * **applicative** (also called **strict**) evaluation strategy:
 +    * parameters are always evaluated **first**
 +    * can be further refined into: **call-by-value** (e.g. as it happens in C) and **call-by-reference** (e.g. as it happens for objects in Java).
 +  * **normal** evaluation strategy (also called **non-strict**,​ and when implemented as part of the PL - **call-by-name**)
 +    * the function is always evaluated **first**
 +    * can be further refined into: **lazy**, which ensures that each expression is evaluated **at most once**
  
-=====Moduri de evaluare a unei expresii: ===== +For more details, see the lecture on lazy evaluation. In Haskell, the default evaluation strategy is **lazy**. However, there are ways in which we can force evaluation to be **strict**. In this lab, we will explore several programming constructs which benefit from lazy evaluation.
-    ​* **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):+===== 8.1. Streams =====
  
-<​code>​(λx.λy.(x + y) 1 2)</​code>​+8.1.1. Define the stream of natural numbers ''​nat :: [Integer]''​\\ 
 +8.1.2. Define the stream of odd numbers. You can use other higher-order functions such as filter, map or zipWith.\\ 
 +8.1.3. Define the stream of Fibonacci numbers
  
-Evident, în urma aplicării funcției de mai sus, expresia se va evalua la 3. +===== 8.2Numerical approximations =====
-Să observăm, însă, cazul în care parametrii funcției reprezintă aplicații de funcții: +
-  +
-<​code>​(λx.λy.(x + y) 1 (λz.(z + 2) 3))</​code>​+
  
-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ționamentam 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.+1. Define the ''​build'' ​function which takes a generator ​''​g'' ​and an initial value ''​a0'' ​and generates the infinite list: ''​[a0,​ g a0, g (g a0), g (g (g a0)), .%%.%%. ]''​
  
-====Evaluare aplicativă====+2. Define the ''​select''​ function which takes a tolerance $math[e] and a list $math[l] and returns the element $math[l_n] which satisfies the following condition: $math[abs(l_n - l_{n+1}) < e]
  
-Evaluarea aplicativă (eager evaluation) este cea în care fiecare expresie este evaluată imediat. În exemplul de mai sus, evaluarea aplicativă va decurge astfel:+=== Numerical Constants ===
  
-<​code>​(λx.λy.(x + y) 1 (λz.(z + 2) 3)) +== Phi ==
-(λx.λy.(x + y) 1 5) +
-6</​code>​+
  
 +We know that $math[\displaystyle \lim_{n \rightarrow \infty} \frac{F_{n+1}}{F_n} = \varphi] (where $math[F_n] is the n-th element of the Fibonacci sequence, and $math[\varphi] is [[https://​en.wikipedia.org/​wiki/​Golden_ratio|"​the Golden Ratio"​]]). More info [[https://​en.wikipedia.org/​wiki/​Golden_ratio#​Relationship_to_Fibonacci_sequence|here]].
  
-====Evaluare normală====+3. Write an approximation with ''​0.001''​ tolerance for the $math[\varphi] constant. Use the previously defined Fibonacci stream.
  
-Spre deosebire de evaluarea aplicativă,​ evaluarea normală va întarzia evaluarea unei expresii, până când aceasta este folosită efectiv. Exemplu:+== Pi ==
  
-<​code>​(λx.λy.(x + y) 1 (λz.(z + 2) 3)) +Consider the sequence:
-(1 + (λz.(z + 2) 3)) +
-(1 + 5) +
-6</​code>​+
  
 +$math[a_{n+1} = a_n + sin(a_n)]; where $math[a_0] is an //initial approximation//,​ randomly chosen (but not 0 because $math[a_{n+1} != a_n]).
  
-===== Exerciții: =====+We know that $math[\displaystyle \lim_{n \rightarrow \infty} a_n \pi]
  
-{{:pp:lazy.zip|Laborator 8 - Schelet}}\\+4Write an approximation with ''​0.001''​ tolerance of the $math[\pi] constant.
  
-==== I. Streams ====+=== Square Root ===
  
-1. construiți șirul numerelor naturale\+Given a number $math[k], we want to find a numerical approximation for $math[\sqrt{k}]Consider the sequence:
-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, .%%.%%.''​)+
  
-==== IIAproximații numerice ====+$math[a_{n+1} ​\frac{1}{2}(a_n + \frac{k}{a_n})];​ where $math[a_0] is an //initial approximation//,​ randomly chosen.
  
-1. Definiți funcția ''​build''​ care primește un generator ''​g''​ și o valoare inițială ''​a0''​ și generează lista infinită: ''​[a0, g a0, g (g a0), g (g (g a0)), .%%.%%. ]''​+We know that $math[\displaystyle \lim_{n \rightarrow \infty} a_n = \sqrt{k}]; more info [[https://​en.wikipedia.org/​wiki/​Methods_of_computing_square_roots#​Babylonian_method | here]].
  
-2Definiți funcția ''​select''​ care primește o toleranță ​$math[e] și o listă $math[l] și întoarce elementul $math[l_n] care satisface proprietatea:​ $math[abs(l_n - l_{n+1}) < e]+5Write a function that approximates ​$math[\sqrt{k}] with ''​0.001''​ tolerance.
  
-=== Constante numerice ​===+=== The Newton-Raphson Method ​===
  
-== phi == +The sequence used for the approximation of the square root can be derived from the [[https://​en.wikipedia.org/​wiki/​Newton%27s_method|Newton-Raphson ​method]], generic ​method for finding the roots of function ​(i.e. the points ​$math[x] ​for which $math[f(x) = 0]). Thus, for a function ​$math[f], ​we have the sequence:
- +
-Știm că $math[\displaystyle \lim_{n \rightarrow \infty} \frac{F_{n+1}}{F_n} = \varphi] (unde $math[F_n] este al n-lea element din șirul lui Fibonacci, iar $math[\varphi] este [[https://​en.wikipedia.org/​wiki/​Golden_ratio|"​proporția de aur"​]]). Mai multe informații [[https://​en.wikipedia.org/​wiki/​Golden_ratio#​Relationship_to_Fibonacci_sequence|aici]]. +
- +
-3. Scrieți o aproximare cu toleranță ''​0.001''​ a constantei $math[\varphi]. Folosiți-vă de stream-ul Fibonacci definit anterior. +
- +
-== pi == +
- +
-Fie șirul: +
- +
-$math[a_{n+1} = a_n + sin(a_n)]; unde $math[a_0] este o //​aproximare inițială//,​ aleasă arbitrar (dar diferită de 0 pentru ca $math[a_{n+1} != a_n]). +
- +
-Știm că $math[\displaystyle \lim_{n \rightarrow \infty} a_n = \pi] +
- +
-4. Scrieți o aproximare cu toleranță ''​0.001''​ a constantei $math[\pi]. +
- +
-=== Rădăcină pătrată === +
- +
-Fiind dat un număr $math[k], vrem să găsim o aproximare numerică pentru $math[\sqrt{k}]. Fie șirul: +
- +
-$math[a_{n+1} = \frac{1}{2}(a_n + \frac{k}{a_n})];​ unde $math[a_0] este o //​aproximare inițială//,​ aleasă arbitrar. +
- +
-Știm că $math[\displaystyle \lim_{n \rightarrow \infty} a_n = \sqrt{k}]; mai multe informații găsiți [[https://​en.wikipedia.org/​wiki/​Methods_of_computing_square_roots#​Babylonian_method | aici]]. +
- +
-5. Scrieți o funcție care aproximează $math[\sqrt{k}] cu toleranța ''​0.001''​. +
- +
-=== Metoda Newton-Raphson === +
- +
-Șirul folosit pentru aproximarea rădăcinii pătrate se poate deriva din [[https://​en.wikipedia.org/​wiki/​Newton%27s_method|metoda ​Newton-Raphson]], ​o metodă ​generică pentru ​găsi rădăcinile unei funcții ​(i.e. punctele ​$math[x] ​pentru care $math[f(x) = 0]). Astfel pentru o funcție ​$math[f], ​avem șirul:+
  
 $math[x_{n+1} = x_n - \frac{f(x_n)}{f'​(x_n)}] $math[x_{n+1} = x_n - \frac{f(x_n)}{f'​(x_n)}]
  
-Știm că $math[\displaystyle \lim_{n \rightarrow \infty} x_n = r\ a.î.\ f(r) = 0].+We know that $math[\displaystyle \lim_{n \rightarrow \infty} x_n = r\ a.î.\ f(r) = 0].
  
-6. Scrieți o funcție care primește o funcție și derivata acesteia și aproximează o rădăcină cu toleranța ''​0.001''​.+6. Write function which takes a function and and its derivative and it approximates a root with ''​0.001'' ​tolerance.
  
-=== Derivate ​===+=== Derivatives ​===
  
-La exercițiul anterior, ne-am folosit de o altă funcție (implementată manual) care să ne calculeze exact derivata funcției $math[f]. Dacă nu avem o astfel de implementare,​ putem aproxima derivata unei funcții într-un anumit punct. Folosindu-ne de definiția derivatei:+We can approximate the derivative of a function in a certain point using the definition of the derivative:
  
 $math[\displaystyle f'​(a)=\lim_{h \rightarrow 0} \frac{f(a+h)-f(a)}{h}] $math[\displaystyle f'​(a)=\lim_{h \rightarrow 0} \frac{f(a+h)-f(a)}{h}]
  
-Putem obține aproximări ​succesive ​din ce în ce mai bune ale derivatei unei funcții într-un punct $math[a], ​folosind un $math[h] ​din ce în ce mai mic.+We can obtain better ​succesive ​approximations of the derivative in a point $math[a], ​using a smaller ​$math[h].
  
-7. Scrieți o funcție care să aproximeze derivata unei funcții într-un punctUrmăriți pașii:+7. Write a function which approximates the derivative of a function in a certain pointfollow the steps:
  
-a) generați șirul: $math[h_0, \frac{h_0}{2},​ \frac{h_0}{4},​ \frac{h_0}{8},​ ...] (unde $math[h_0] ​este o //aproximare inițială//, aleasă arbitrar)\\ +a) generate the sequence: $math[h_0, \frac{h_0}{2},​ \frac{h_0}{4},​ \frac{h_0}{8},​ ...] (where $math[h_0] ​is a randomly chosen ​//initial approximation//)\\ 
-b) generați lista aproximarilor lui $math[f'​(a)], ​folosind ​formula ​de mai sus\\ +b) generate the list of approximations for $math[f'​(a)], ​using the formula ​above\\ 
-c) scrieți funcția care primește o funcție ​$math[f] ​și un punct $math[a] ​și aproximează ​$math[f'​(a)] ​cu toleranța ​''​0.001'', ​folosindu-vă de subpunctele anterioare.+c) write the function that takes a function ​$math[f] ​and a point $math[a] ​and approximates ​$math[f'​(a)] ​with ''​0.001'' ​toleranceusing the previous steps.
  
-=== Integrale ​===+=== Integrals (: ===
  
-Dându-se o funcție ​$math[f], ​putem aproxima integrala definită pe intervalul ​$ [a, b]$, folosind aria trapezului definit de $math[a, b, f(a), f(b)]:+Given a function ​$math[f], ​we can approximate the definite integral on $ [a, b]$, using the area of the trapezoid defined by $math[a, b, f(a), f(b)]:
  
 $math[\displaystyle \int_{a}^{b} f(x) dx \approx (b - a)\frac{f(a)+f(b)}{2}] $math[\displaystyle \int_{a}^{b} f(x) dx \approx (b - a)\frac{f(a)+f(b)}{2}]
  
-Putem obține o aproximare mai bună împărțind intervalul în două și însumând aria celor două trapeze definite de $math[a, m, f(a), f(m)] și de $math[m, b, f(m), f(b)] (unde $math[m] ​este mijlocul intervalului ​$ [a, b]$). Putem obține o aproximare și mai bună împărțind aceste două intervale în două și tot așa.+We can obtain a better approximation by dividing the interval in two and adding the area of the two trapezoids defined by $math[a, m, f(a), f(m)] and $math[m, b, f(m), f(b)] (where $math[m] ​is the middle of the interval ​$ [a, b]$). We can obtain ​better approximation by dividing these intervals in two and so on.
  
-8. Scrieți o funcție care să aproximeze integrala unei funcții pe un interval. ​Urmăriți pașii:+8. Write a function which approximates the integral of a function on an interval. ​Follow the steps:
  
-a) Scrieți o funcție care primește o funcție ​$math[f] ​și două puncte ​$math[a, b] și calculează aria trapezului ​$math[a, b, f(a), f(b)]\\ +a) Write a function which takes a function ​$math[f] ​and two points ​$math[a, b] and calculates the area of the trapezoid ​$math[a, b, f(a), f(b)]\\ 
-b) Scrieți o funcție care primește o listă ​(crescătoarede puncte și inserează între oricare două elemente mijlocul acestor:+b) Write a function which takes a (ascendinglist of points and inserts between any two points their middle:
  
 ''​[1,​ 4, 7, 10, 13] -%%>%% [1, 2.5, 4, 5.5, 7, 8.5, 10, 11.5, 13]''​ ''​[1,​ 4, 7, 10, 13] -%%>%% [1, 2.5, 4, 5.5, 7, 8.5, 10, 11.5, 13]''​
  
-c) Scrieți o funcție care primește o funcție ​$math[f] ​și o listă de puncte ​$math[p_0,\ p_1,\ p_2,\ p_3,\ ...] și întoarce lista ariilor trapezelor descrise de două puncte ​consecutive:​\\+c) Write a function which takes a function ​$math[f] ​and a list of points ​$math[p_0,\ p_1,\ p_2,\ p_3,\ ...] and returns the list containing the areas of trapezoids defined by two consecutive ​points:\\
  
 $math[(p_0, p_1, f(p_0), f(p_1));\ (p_1, p_2, f(p_1), f(p_2));\ (p_2, p_3, f(p_2), f(p_3));\ ...] $math[(p_0, p_1, f(p_0), f(p_1));\ (p_1, p_2, f(p_1), f(p_2));\ (p_2, p_3, f(p_2), f(p_3));\ ...]
  
-d) Scrieți o funcție care primește o funcție ​$math[f] ​și două puncte ​$math[a, b] și aproximează ​$math[\displaystyle \int_{a}^{b} f(x) dx] cu toleranța ​''​0.001'', ​folosindu-vă de subpunctele anterioare.+d) Write a function which takes a function ​$math[f] ​and two points ​$math[a, b] and approximates ​$math[\displaystyle \int_{a}^{b} f(x) dx] with ''​0.001'' ​toleranceusing the previous steps.
  
 ===== Recommended Reading ===== ===== Recommended Reading =====
  
-  * [[http://​worrydream.com/​refs/​Hughes-WhyFunctionalProgrammingMatters.pdf| Why Functional Programming Matters (în special secțiunea ​4 "​Gluing Programs Together", ​de unde sunt inspirate exercițiile din laborator)]]+  * [[http://​worrydream.com/​refs/​Hughes-WhyFunctionalProgrammingMatters.pdf| Why Functional Programming Matters (especially section ​4 "​Gluing Programs Together", ​where the lab exercises are inspired from)]]