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:2023:haskell:l07 [2023/04/19 23:37]
tpruteanu
pp:2023:haskell:l07 [2023/04/27 01:17] (current)
mihai.udubasa [Lambda calculus as a programming language (optional)] fix typo
Line 69: Line 69:
 **A:** We can evaluate any of them, and it is guaranteed by [[https://​en.wikipedia.org/​wiki/​Church%E2%80%93Rosser_theorem | Church-Rosser theorem]] that if the expression is reducible, we will eventually get the same $ \beta $**-normal form**. **A:** We can evaluate any of them, and it is guaranteed by [[https://​en.wikipedia.org/​wiki/​Church%E2%80%93Rosser_theorem | Church-Rosser theorem]] that if the expression is reducible, we will eventually get the same $ \beta $**-normal form**.
  
-To not just randomly choose **redexes**,​ there exist // reduction strategies //, from which we will use the **Normal Order** and **Applicative Order**: \\+To not just randomly choose **redexes**,​ there exist //reduction strategies//,​ from which we will use the **Normal Order** and **Applicative Order**: \\
   * **Normal Order** evaluation consist of always reducing the //​leftmost//,​ //​outermost//​ **redex** (whenever possible, subsitute the arguments into the function body) \\   * **Normal Order** evaluation consist of always reducing the //​leftmost//,​ //​outermost//​ **redex** (whenever possible, subsitute the arguments into the function body) \\
   * **Applicative Order** evaluation consist of always reducing the //​leftmost//,​ //​innermost//​ **redex** (always reduce the function argument before the function itself) \\   * **Applicative Order** evaluation consist of always reducing the //​leftmost//,​ //​innermost//​ **redex** (always reduce the function argument before the function itself) \\
Line 86: Line 86:
  
 The [[https://​en.wikipedia.org/​wiki/​Church%E2%80%93Turing_thesis | Church-Turing thesis]] asserts that any //​computable//​ function can be computed using lambda calculus (or Turing Machines or equivalent models). \\ The [[https://​en.wikipedia.org/​wiki/​Church%E2%80%93Turing_thesis | Church-Turing thesis]] asserts that any //​computable//​ function can be computed using lambda calculus (or Turing Machines or equivalent models). \\
-For the curios, a series of additional exercises covering this topic can be found here: [[pp:​2023:​haskell:​l07-extra|Lambda Calculus as a programming language]]. \\+For the curious, a series of additional exercises covering this topic can be found here: [[pp:​2023:​haskell:​l07-extra|Lambda Calculus as a programming language]]. \\
  
 ===== 7.2 Intro to Haskell ===== ===== 7.2 Intro to Haskell =====
Line 101: Line 101:
 Remember: [[pp:​2023:​scala:​l01|Lab 1. Introduction to Scala]] Remember: [[pp:​2023:​scala:​l01|Lab 1. Introduction to Scala]]
  
-**7.2.1.** Implement a tail-recursive function that computes the factorial of a natural number. ​Start from the code stub below:+**7.2.1.** Implement a tail-recursive function that computes the factorial of a natural number.
 <code haskell> <code haskell>
 fact :: Int -> Int fact :: Int -> Int
 fact = undefined fact = undefined
 </​code>​ </​code>​
-**7.2.2.** Implement a tail-recursive function that computes the greatest common divisor of two natural numbers:+**7.2.2.** Implement a tail-recursive function that computes the greatest common divisor of two natural numbers.
 <code haskell> <code haskell>
-gcd :: Int -> Int -> Int +mygcd :: Int -> Int -> Int 
-gcd a b = undefined+mygcd a b = undefined
 </​code>​ </​code>​
 **7.2.3.** Implement the function ''​mySqrt'' ​ which computes the square root of an integer $ a $. **7.2.3.** Implement the function ''​mySqrt'' ​ which computes the square root of an integer $ a $.
Line 122: Line 122:
 } }
 </​code>​|<​code haskell> ​ </​code>​|<​code haskell> ​
-f l = case l of {+f l = case l of
   [] -> ...   [] -> ...
-  (x:​xs) ​=> ... +  (x:​xs) ​-> ...
-}+
 </​code>​ | <code haskell> </​code>​ | <code haskell>
 f [] = ... f [] = ...
Line 134: Line 133:
 </​code>​ | </​code>​ |
  
-**7.2.4.** Implement funtions ''​minimum''​ and ''​maximum''​ that take a list of ints, and return the smallest/​biggest value in the list.+**7.2.4.** Implement funtions ''​mymin''​ and ''​mymax''​ that take a list of ints, and return the smallest/​biggest value in the list.
  
 **7.2.5.** Implement a function ''​unique''​ that takes a list of ints, and removes all duplicates. **7.2.5.** Implement a function ''​unique''​ that takes a list of ints, and removes all duplicates.
Line 144: Line 143:
   * a string representation of the number otherwise   * a string representation of the number otherwise
  
-**7.2.7.** Extend the function from **7.2.5.** with the following rules:+**7.2.7.** Extend the function from **7.2.6.** with the following rules:
   * **'​Bazz'​** if the number is divisible by 7   * **'​Bazz'​** if the number is divisible by 7
   * **'​FizzBazz'​** if the number is divisible by 21   * **'​FizzBazz'​** if the number is divisible by 21
Line 168: Line 167:
 </​code>​ </​code>​
 </​note>​ </​note>​
 +
 +==== Types in Haskell ====
 +
 +In Haskell, functions are curried by default, **i.e.** a function:
 +<code haskell>
 +f a b = ...
 +</​code>​
 +is the same as:
 +<code haskell>
 +f = \a -> \b -> ...
 +</​code>​
 +
 +So, if $ a $ is a ''​Int''​ and $ b $ a ''​Double'',​ and $ f $ returns a ''​Char'',​ it would have the following type:
 +<code haskell>
 +f :: Int -> Double -> Char
 +</​code>​
 +
 +**7.2.8.** Check the type signature of the following functions:
 +  * ''​foldl''​
 +  * ''​foldr''​
 +  * ''​filter''​
 +  * ''​map''​
 +
 +<note important>​
 +If a function is not ambigous, ''​ghc''​ can infer the type signature, for **educational** purposes, going forward you will have to write signatures for all functions you define, this is considered good practice and helps prevent bugs.
 +</​note>​
 +
 +<note tip>
 +In ''​ghci'',​ you can check the type of a expression with: '':​t''​
 +</​note>​
 +
 +===== 7.3 Brain Twisters =====
 +
 +**7.3.1.** Implement ''​map''​ using ''​foldl''​ and ''​foldr''​.
 +<code haskell>
 +mymapl :: (a -> b) -> [a] -> [b]
 +mymapr :: (a -> b) -> [a] -> [b]
 +</​code>​
 +
 +**7.3.2.** Implement ''​filter''​ using ''​foldl''​ and ''​foldr''​.
 +<code haskell>
 +myfilterl :: (a -> Bool) -> [a] -> [a]
 +myfilterr :: (a -> Bool) -> [a] -> [a]
 +</​code>​
 +
 +**7.3.3.** Implement ''​foldl''​ using ''​foldr''​.
 +<code haskell>
 +myfoldl :: (a -> b -> a) -> a -> [b] -> a
 +</​code>​
 +
 +**7.3.4.** Implement ''​bubbleSort''​.
 +<code haskell>
 +bubbleSort :: [Int] -> [Int]
 +</​code>​
 +
 +**7.3.5.** Implement ''​quickSort''​.
 +<code haskell>
 +quickSort :: [Int] -> [Int]
 +</​code>​