Haskell: Flow of Control

Haskell: Flow of Control

Haskell: Flow of Control CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Wednesday, February 27, 2019 Glenn G. Chappell Department of Computer Science University of Alaska Fairbanks [email protected] © 2017–2019 Glenn G. Chappell Review PL Category: Functional PLs [1/2] Imperative programming: code tells a computer what to do. Declarative programming: code tells a computer what is true. Functional programming (FP) is a declarative programming style that generally has the following characteristics. § Computation is considered primarily in terms of the evaluation of functions—as opposed to execution of tasks. § Functions are a primary concern. Rather than mere repositories for code, functions are values to be constructed and manipulated. § Side effects* are avoided. A function’s only job is to return a value. *A function has a side effect when it makes a change, other than returning a value, that is visible outside the function. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 2 Review PL Category: Functional PLs [2/2] A functional programming language is a PL designed to support FP well. A pure functional PL goes further, and does not support mutable data at all. There are no side effects in a pure functional PL. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 3 Review Haskell: Functions — Basic Syntax [1/2] Identifiers begin with a letter or underscore, and contain only letters, underscores, digits, and single quotes ('). There are two kinds of identifiers. § Normal identifiers begin with a lower-case letter or underscore. These name variables and functions. § Special identifiers begin with an UPPER-CASE letter. These name modules, types, and constructors. (This is not merely a convention!) myVariable -- Normal _my_Function'_33 -- Normal MyModule -- Special For code from this topic, see func.hs. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 4 Review Haskell: Functions — Basic Syntax [2/2] To define a function, write what looks like a call to the function, an equals sign, and then an expression. addem a b = a+b Parentheses may be used around individual arguments, due to precedence & associativity issues. addem 18 (5*7) Use where to introduce a block of local definitions. lenSquared x y = sq x + sq y where sq z = z*z 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 5 Review Haskell: Functions — Defining Operators We can define new infix binary operators. We can optionally set an operator’s precedence and associativity. a +$+ b = 2*a + b infixl 6 +$+ -- Left-associative, precedence level 6 Use a regular function as an infix binary operator by surrounding its name with backquotes (`). 2 `addem` 3 Use an infix binary operator as a regular function by surrounding its name with parentheses. (+$+) 5 7 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 6 Review Haskell: Functions — Currying Currying: simulating a multiple-argument function using a single- argument function that returns a function. Multiple-argument functions in Haskell are curried. addem x y = x+y add2 = addem 2 > add2 3 5 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 7 Review Haskell: Functions — Higher-Order Functions, Lambda Functions Higher-order function: function that acts on functions. rev f a b = f b a sub x y = x-y rsub = rev sub > rsub 5 8 -3 Lambda function: function with no name. > (\ x -> x*x) 5 25 > map (\ x -> x*x) [2, 3, 8] [4,9,64] 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 8 Review Haskell: Lists — Lists & Tuples List: holds an arbitrary number of items, all of the same type. [1, 4, 2] [] ['h','e','l','l','o'] "hello" -- Same as previous line [[1,2],[],[3],[4,5,6]] [1,3..] -- Infinite list: ALL positive odd integers Tuple: holds a fixed number of items, possibly of different types. (True, "abc", 34.6, [3,8]) For code from this topic, see list.hs. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 9 Review Haskell: Lists — List Primitives Three list primitives. 1. Construct an empty list. [] 2. Cons: construct a list given its first item and a list of other items. Uses the infix colon (:) operator. [5, 2, 1, 8] 5:[2, 1, 8] -- Same as above 5:2:1:8:[] -- Also same; ":" is right-associative 3. Pattern matching for lists. x:xs -- Pattern that matches a nonempty list 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 10 Review Haskell: Lists — Other List Syntax List comprehension: > [ x*y | x <- [3, 2, 1], y <- [10, 11, 12] ] [30,33,36,20,22,24,10,11,12] > [ a | a <- [6,5,4,3,2,1], a > 3 ] [6,5,4] 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 11 Review Haskell: Lists — Lists & Recursion [1/2] A function that takes a list will often be recursive. The base case handles the empty list. The recursive case handles a nonempty list. This might do a computation involving the head (b above) and make a recursive call on the tail (bs above). TO DO § Write a function myMap that replicates the Prelude function map. § Look at the Prelude function filter. § Replicate filter as myFilter. A predicate is a function that returns a Boolean value. A useful construction: if COND then EXPR1 else EXPR2. § COND is an expression of type Bool. If it is True, then EXPR1 is returned. If it is False, then EXPR2 is returned. § Expressions EXPR1 and EXPR2 must have the same type. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 12 Review Haskell: Lists — Lists & Recursion [2/2] Sometimes other kinds of recursion are used. TO DO § Write a function lookInd that does item lookup by index (zero- based) in a list. Useful § The pattern “_” means unused parameter. § Function error takes a String and returns any type. When it executes, it crashes, printing an error message, which should include the given string. § undefined is like error, but it takes no arguments. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 13 Haskell: Flow of Control Introduction Flow of control refers to the ways a PL determines what code is executed. For example, flow of control in Lua includes: § Selection (if … elseif … else). § Iteration (while, for). § Function calls. § Coroutines. § Threads. § Exceptions. Haskell has very different flow-of-control facilities from most PLs that are oriented toward imperative programming. Key Idea. Things that are done with traditional flow-of-control constructs in other programming languages are often done differently in Haskell. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 14 Haskell: Flow of Control Pattern Matching, Recursion, Lazy Evaluation [1/5] We have seen that Haskell has a useful pattern matching facility, which allows us to choose one of a number of function definitions. The rule is that the first definition with a matching pattern is the one used. isEmpty [] = True isEmpty (x:xs) = False -- fibo the SLOW way fibo 0 = 0 fibo 1 = 1 fibo n = fibo (n-2) + fibo (n-1) In many of the places we would use an if … else construction in other PLs, we use pattern matching in Haskell. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 15 Haskell: Flow of Control Pattern Matching, Recursion, Lazy Evaluation [2/5] Haskell also makes heavy use of recursion. lookInd 0 (x:xs) = x lookInd n (x:xs) = lookInd (n-1) xs lookInd _ [] = error "lookInd: index out of range" In places where we would use a loop in an imperative PL, we use recursion in Haskell. Recursion can be less costly in Haskell than in PLs like C++, because of Haskell’s required tail-call optimization (TCO). TCO means that a tail call does not use additional stack space. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 16 Haskell: Flow of Control Pattern Matching, Recursion, Lazy Evaluation [3/5] By default, Haskell does lazy evaluation. This allows for infinite lists. We have said that we can generate these even without the “..” syntax. But how? Here is an idea. -- listFrom n -- Returns the infinite list [n, n+1, n+2, ...]. listFrom n = n:listFrom (n+1) Is the above code acceptable? It does recursion with no base case. But this is not a problem, thanks to lazy evaluation. A recursive call is only made if further list items are needed. Using only a finite number of items guarantees that the recursion terminates. This is called corecursion: § A stream of values is generated recursively, as needed. § The recursion terminates when no more values are requested. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 17 Haskell: Flow of Control Pattern Matching, Recursion, Lazy Evaluation [4/5] Something else we can do: write our own if … else, as a function. -- myIf condition tVal fVal -- Returns tVal if condition is True, fVal otherwise. myIf True tVal _ = tVal myIf False _ fVal = fVal Thanks to lazy evaluation, no more than one of tVal, fVal is ever evaluated. Here is the slow Fibonacci algorithm using myIf. fibo n = myIf (n <= 1) n (fibo (n-2) + fibo (n-1)) 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 18 Haskell: Flow of Control Pattern Matching, Recursion, Lazy Evaluation [5/5] And here is myFilter, reimplemented using myIf. myFilter p [] = [] myFilter p (x:xs) = myIf (p x) (x:rest) rest where rest = myFilter p xs It turns out that the combination of pattern matching, recursion, and lazy evaluation, together with function calls, are all we need. We can build any flow-of-control construct out of these. However, Haskell has other flow-of-control facilities, for convenience. Next we look at a few of these. 27 Feb 2019 CS F331 / CSCE A331 Spring 2019 19 Haskell: Flow of Control Selection — Introduction Selection allows us to choose one of multiple options to execute.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    44 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us