* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download An introduction to functional programming using Haskell
Survey
Document related concepts
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
Transcript
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?