Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Scala (programming language) wikipedia , lookup
Anonymous function wikipedia , lookup
Falcon (programming language) wikipedia , lookup
Curry–Howard correspondence wikipedia , lookup
Closure (computer programming) wikipedia , lookup
Intuitionistic type theory wikipedia , lookup
An introduction to functional programming using Haskell CENG242 –Recitation 1 Introduction: Haskell The most popular purely functional, lazy programming language “Functional programming language”: a program is a collection of mathematical functions “Purely functional”: all variables refer to immutable, persistent values that is, new values can be created, but existing ones cannot be modified no destructive updates “Lazy”: expressions are evaluated “by need” HUGS A well-known Haskell system An interpreter; test and debug programs in an interactive environment Can be downloaded from its webpage http://haskell.org/hugs Prelude module is always loaded and contains the standard definitions ( (:) operator, (+), (*), fst, etc.) Hugs will not run without the prelude file. Some helpful commands: :?, :quit, :type / :t, :load / :l, :reload / :r, :main, etc. HUGS Using the HUGS command prompt, you can evaluate expressions; however you cannot make definitions. Hugs> take 3 a where a = [1, 2, 3, 4, 5, 6, 7] [1,2,3] Hugs> b = take 3 a where a = [1, 2, 3, 4, 5, 6, 7] ERROR - Syntax error in input (unexpected `=') You can define new variables and functions in files and load them from Haskell prompt. --sample.hs module Sample where b = take 3Hugs>:load a where a sample = [1, 2, 3, 4, 5, 6, 7] Hugs>b [1,2,3] Haskell Value and type concepts are essential in grasping the main idea of Haskell programming language. All computations are done via the evaluation of expressions (syntactic terms) to yield values (abstract entities that we regard as answers). a =1 b = [1, 2, 3] Every value has an associated type. ( :: can be read as ‘has type’) a :: Integer b :: [Integer] Cont’d… Haskell is case-sensitive Type names and constructor names begin with an upper-case letter Value names begin with lower-case letter e.g Expr or Rectangle e.g. x or intTemp Function names begin with lower-case letter (functions are values too) e.g. square or filter Types Basic types: Integer, String, Float, Double, Char, … [X] : a list of x values X -> Y: a function from X value to Y value (X,Y, Z) : a tuple of a X value, a Y value and a Z value [1,2,3,4] [] Lists are homogeneous (elements are of the same type) Pair: (4, „a‟) Triple: (“hi”, [1,2], 6) Elements do not need to have the same types … Strong Typing len :: [Integer] -> Integer len [] = 0 len (x:xs) = len(xs) + 1 number :: [Integer] number = [7, 19, 13] n :: Integer n = len numbers Every expression has a type which can be deduced at compile-time. The main advantage of statically typed languages is wellknown: All type errors are detected at compile-time. Type Inference In Haskell, writing type annotations is optional Use them to express the intended meaning of your functions Omit them if the meaning is “obvious” When omitted, Haskell finds the type for you! …in fact, the best possible type (also called, the principle type) Values and Types All Haskell values are "first-class"---they may be passed as arguments to functions, returned as results, placed in data structures, etc. Functions are values too! Hence you can pass functions as arguments to other functions (called higher order functions) Haskell types, on the other hand, are not first-class. Types in a sense describe values, and the association of a value with its type is called a typing. The static type system ensures that Haskell programs are type safe. Some basic functions length, tail, head, null ++, == , /= fst, snd sqrt show, read Defining Functions square x = x * x Here we’re defining a function square that takes one argument, which we call x. Then we say that the value of square x is equal to x*x Functions in Haskell are normally defined by a series of equations (every line gives an equation in the following code): func 0 = 1 func 1 = 5 func 2 = 2 func _ = -1 –Underscore (_) means ‘don’t care’ Defining Functions Consider the following function: unitImpulse :: Integer -> Integer unitImpulse 0 = 1 unitImpulse _ = 0 The left-hand sides of the equations contain patterns such as 0 and _. In a function application these patterns are matched against actual parameters. If the match succeeds, the right-hand side is evaluated and returned as the result of the application. Note that a stronger match is always preferred over a weaker match, otherwise the above function would always yield 0. Defining Functions Consider the previous example len :: [Integer] -> Integer len [] = 0 len (x:xs) = len(xs) + 1 Haskell can match lists as the first element and remaining portion of list. It’s also possible to match the last element and the rest len :: [Integer] -> Integer len [] = 0 len (xs:x) = len(xs) + 1 –Note the difference If-then-else expressions if e1 then e2 else e3 signum x = if x < 0 then -1 else if x > 0 then 1 else 0 You must have both a then and an else clause Case expressions case expressions are used when there are multiple values that you want to check against casefunc x = case x of 0 -> 1 1 -> 5 2 -> 2 _ ->-1 Guards Enable you to allow piecewise function definitions to be taken according to arbitrary Boolean expressions. e.g. compare x y | x < y = “The first is less” | x > y = “The second is less” | otherwise= “They are equal” or; compare2 x y | x < y = "The first is less“ | x > y = "The second is less" compare2 _ _ = "They are equal" Cont’d… More complicated functions can be built from simpler functions using function composition Function composition: taking the result of one function and use it as an argument e.g. square (sqrt 2) Here, parenthesis is necessary, otherwise the interpreter would think that you try to get the value of “square sqrt” Another way to express function composition is using the (.) function e.g. (square.sqrt) 2 Recursion No loops in Haskell Uses recursion Divide and conquer! e.g. exponential a 0 = 1 exponential a b = a * exponential a (b-1) lenFunc [] = 0 lenFunc (x:xs) = 1 + lenFunc xs Cont’d… e.g. filterFunc func [] = [] filterFunc func (x:xs) = if func x then x : filterFunc func xs else filterFunc func xs e.g. reverse [] = [] reverse (x:xs) = reverse xs ++ [x] Type definitions data Color = Red | Green | Blue f Red = 1 f Blue = 2 f _ = 3data Shape = Rectangle Float Float | Circle Float Area (Rectangle x y) = x * y Area (Circle r) = pi * r * r Red, Green, Blue, Rectangle, and Circle are called constructors Cont’d… data keyword provides the capability to define new types. data Color = Red | Green | Blue data Bool = True | False Both Bool and Color are examples of enumerated types, since they consist of a finite number of nullary data constructors. Cont’d… --Point is the Cartesian product of two values of same type --Note x which is lower case. It’s possible to express a new --type, such as Point of Integer (Point Integer) or Point of Float data Point x = Pt x x p :: Point Integer p = Pt 2 3 You should distinguish between applying a data constructor to yield a value, and applying a type constructor to yield a type. The former happens at run-time and is how we compute things in Haskell, whereas the latter happens at compiletime and is part of the type system's process of ensuring type safety. Cont’d… It’s crucial to understand the distinction between data constructors and type constructors. --Point is a type constructor, whereas Pt is a data constructor data Point x = Pt x x --For type enforcement, we use the type constructor --In equations, we use data constructors since we try to match --values sumCoord :: Point Integer -> Integer sumCoord (Pt a b) = a + b p :: Point Integer p = Pt 2 3 s = sumCoord p Identifiers such as ‘x' above are called type variables, and are uncapitalized to distinguish them from specific types such as Int. Type Synonyms For convenience, Haskell provides a way to define type synonyms; i.e. names for commonly used types. type String = [Char] type AssocList a b = [(a,b)] (Polymorphism) String is simply a list of characters Examples data List a = Nil | Cons a (List a) listLength Nil = 0 listLength (Cons x xs) = 1 + listLength xs data BinaryTree a = Leaf a | Branch (BinaryTree a) a (Binary Tree a) treeSize (Leaf x) = 1 treeSize (Branch left x right) = 1 + treeSize left + treeSize right Comments --Computes the length of a list len :: [Integer] -> Integer len [] = 0 len (x:xs) = len(xs) + 1 {number :: [Integer] number = [7, 19, 13] n :: Integer n = len numbers -} Any questions?