PJP - Překladače · 2017. 11. 10. · Introduction –Basic concepts (1) Function Gives output...
Transcript of PJP - Překladače · 2017. 11. 10. · Introduction –Basic concepts (1) Function Gives output...
Programming
ParadigmsFunctional languages
Ing. Marek Běhálek Ph.D.FEI VŠB-TUO
EA404 / 597 32 5879
http://www.cs.vsb.cz/[email protected]
Presentation is based on original course materials from doc. Ing Miroslav Beneš Ph.D.
Introduction – Why functional
programming maters
Functional languages provides a framework in which the crucial ideas of modern programming are presented in clearest possible way.
Functional languages are increasingly being used as components of larger systems.
Declarative style of programming
Why to learn functional programming? Simple model of programming New ideas and different approaches
Our lectures will be: Simplified – not all aspects (mainly theoretical) will be explored. Practically focused – we will use Haskell…
We will (not strictly) follow: Thompson S.: Haskell: The Craft of Functional Programming
Functional programming 2
Introduction – Basic concepts
(1)
Function Gives output values based on input values
A result based on parameters or arguments
A process of giving particular inputs is called functional application
Example Function giving distance between two cities.
Functions evaluation You know how to evaluate an expression: (7-3)*2
In functional programming A program is a set of definitions of functions and other values
These definitions model our particular problem.
We evaluate them to obtain results.
Definitions name :: Type
name = expression
Functional programming 3
Introduction – Basic concepts
(2)
Function definitions square :: Int -> Int - declaration, must not be given!
square n = n * n
square applications square 5 = 5 * 5 square (2+4) = (2+4) * (2+4)
Function composition Output of one function becomes input of another one. Powerful abstraction mechanism rotate :: Picture -> Picture
rotate = flipH . flipV alternatively: rotate x = flipH (flipV x)
‘.’ is operator (like for example +)
Type checking Definitions express a constrains, can lead to type error.
Functional programming 4
Haskell – Hugs (1)
We will use Hugs98
Nearly full implementation of programming language Haskell 98
Some extension implemented
Basic resources
http://haskell.org
Language specification and other resources
http://haskell.org/hugs
Installation packages (Win / Unix)
User’s manual (is a part of installation)
Functional programming 5
Haskell –Hugs (2) Basic evaluation: calculator
$ hugsPrelude> 2*(3+5)16
Script: containing user’s definitions $ hugs example.hs
Editing of source code :edit [file.hs] :e
Loading of source code:load [file.hs]:reload
Exiting work:quit
Help:?
Functional programming 6
Haskell – Hugs (3)
example.hsmodule Example where
-- Function computing sum of two numbers
sum x y = x + y
Example.lhs> module Example where
Function computing factorial
> f n = if n == 0 then 1 else n * f (n-1)
Functional programming 7
Haskell – Hugs (4)
Module has a name and contains definitionsmodule Ant where
…
Modules can be importedmodule Example where
import Ant
…
Prelude - similar to java.lang package.
Hiding functions: import Prelude hiding (max, min)
Functional programming 8
Haskell – Hugs (5)
Layout
Indentations are important!
Strange errors with ‘;’
▪ funny x = x +
1
ERROR …. : Syntax error in expression (unexpected ‘;’)
Names
Identifiers - begin with letter, followed by a sequence of letter
digits, underscores and single quotes.
Names used in definition of values begin with small letters.
Types and constructors begins with capital letters.
Functional programming 9
Haskell – Basic data types
1::Int +, -, *, ^, div, mod, abs, negate, == ‘mod’ – infix version, we can use any function that way!
‘a’::Char Special characters: ‘\t’, ‘\n’, ‘\\’,’\’’, ‘\”’ Prelude functions:
ord :: Char -> Int, chr :: Int -> Char, toUpper, isDigit
Library Char
True,False::Bool &&, ||, not, ==
3.14::Float +, -, *, /, ^, **, ==, /=, <, >, <=, >= abs, acos, asin, sin, cos, celing, floor, exp, fromInt, log,
negate, pi signum…
Functional programming 10
Haskell – Operators
You can build new operators in Haskell Operators are build for operator’s symbols:
! # & $ % * + - . / < > = ? \ ^ | : ~
Similar to function definition (&&&) :: Int -> Int-> Int
x &&& y = x +y
Functional programming 11
Haskell – Practical exercises
(1)1. Run Hugs2. Evaluate expression (4+2)/(5-6)3. Try to use different operators.4. Create source file example.hs(lhs)5. Implement function square :: Int -> Int
Use its type definition, then remove it and observe differences in behavior.
6. Implement function sum :: Int -> Int -> Int, hides existing one in module Prelude.
7. Create function complex_computation that will be a composition of functions square and sum.
8. Use this function in infix notation.9. Define your own operator for
complex_computation.
10. Try to find what is operator $$ for.
Functional programming 12
Haskell – Programming in
Haskell
How to write programs in Haskell? Recursion
Simple examples: factorial, Fibonacci numbers.
Function definition – revisited Guard expressions max :: Int -> Int -> Int
max x y
| x>=y = x
| otherwise = y
Conditional expression if condition then m else n
It is “expression” not a statement!Functional programming 13
Haskell – Pattern matching
Equation and pattern unification (pattern matching): f pat11 pat12 ... = rhs1
f pat21 pat22 ... = rhs2
...
First corresponding equation is chosen.
If there is none error
Functional programming 14
Haskell – Examples
Factorial fakt1 n = if n == 0 then 1
else n * fakt1 (n-1)
fakt2 0 = 1fakt2 n = n * fakt2 (n-1)
fakt3 0 = 1fakt3 (n+1) = (n+1) * fakt3 n
fakt4 n | n == 0 = 1| otherwise = n * fakt4 (n-1)
Fibonacci numbersfib :: Int -> Intfib 0 = 0fib 1 = 1fib (n+2) = fib n + fib (n+1)
Functional programming 15
Haskell – Practical exercises
(2)
1. Create a function computing Fibonacci numbers, consider different possibilities.
2. Create a function computing:1. remainder;
2. divider;
3. smallest common divider;
Functional programming 16
Haskell – List and tuples (1) List and tuples are basic concepts to building complex data
structures. Important note - polymorphism and high order functions
Ordered tuples (a,b,c,...) (1,2) :: (Int,Int) (1,['a','b'])::(Int, [Char]) () :: ()
We can use functions: fst (1,2) = 1 Pattern matching very usefull. Consider example:
fibStep :: (Int, Int) -> (Int, Int)fibStep (u,v) = (v,u+v)fibPair :: Int -> (Int,Int)fibPair n | n==0 = (0,1)| otherwise = fibStep (fibPair (n-1))
newFib :: Int -> IntnewFib = fst . fibPair
Which one is faster?
Functional programming 17
Haskell – List and tuples (2)
data List a = Cons a (List a) (x:xs)
| Nil []
1 2 3
1 : ( 2 : ( 3 : [ ] ) )
Functional programming 18
Haskell – List and tuples (3)
Lists [a] Empty list []
Non-empty list (x:xs)
1:2:3:[] :: [Int]
[1,2,3] :: [Int]
We can even have a list of functions! Functions are first class values in Haskell! [fib, newFib] :: [(Int -> Int)]
List length length [] = 0
length (x:xs) = 1 + length xs Comment: be aware of name conflict with previously defined
functions!
Functional programming 19
Haskell – Data types
User defined data types data Color = Black
| White
data Tree a = Leaf a| Node a (Tree a) (Tree a)
type String = [Char]
type Table a = [(String, a)]
Functional programming 20
Haskell – Patterns
variable inc x = x + 1
constant not True = False not False = True
List length [] = 0 length (x:xs) = 1 + length xs
tupels plus (x,y) = x+y
User’s type constructor nl (Leaf _) = 1 nl (Node _ l r) = (nl l) + (nl r)
Named pattern’s parts duphd p@(x:xs) = x:p
Another patterns - n+k fact 0 = 1 fact (n+1) = (n+1)*fact n
Functional programming 21
Haskell – Practical exercises
(3)1. Create a function that computes length of a list.
2. Create a function that merge two lists into one list.
3. Create a function that merge two lists into one list of tuples.
4. Create a function that reverse a list.
5. Create a function that merges two lists into one using given function to merge specific elements together. Given lists: [1,2,3] [1,2,3] and operation *, the result should be
[1,4,9].
6. Create a function that product scalar multiplication if two vectors.
7. Create a function that compute Cartesian product of two vectors.
8. Create a function that find the smallest element in the list. Consider input restrictions.
Functional programming 22
Haskell – Type classes
Type class – set of types with specific
operations
Num: +, -, *, abs, negate, signum, …
Eq: ==, /=
Ord: >, >=, <, <=, min, max
Constrains, type class specification
elem :: Eq a => a -> [a] -> Bool
minimum :: Ord a => [a] -> a
sum :: Num a => [a] -> a
Functional programming 23
Haskell – Endless lists
ones = 1 : ones
natFrom n = n : natFrom (n+1)
natFrom 1 = 1 : 2 : 3 : … = [1..]
How it is possible? – Lazy evaluation, we will talk about it later…
1
Functional programming 24
Haskell – Arithmetic rows
[m..n]
[1..5] = [1,2,3,4,5]
[m1,m2..n]
[1,3..10] = [1,3,5,7,9]
[m..]
[1..] = [1,2,3,4,5,…]
[m1,m2..]
[5,10..] = [5,10,15,20,25,…]
Functional programming 25
Haskell – List comprehensions
Consider mathematic definitions Define a set containing even natural numbers smaller then
or equal to 10.
List comprehensions [n | n <- [1..10], n ‘mod’ 2 == 0]
List generator: n <- [1..10]
Examples: allEven xs = (xs == [x | x<-xs, isEven x])
allOdd xs = (xs == [x | x<-xs, not(isEven
x])
cart_prod xs ys = [(x,y) | x<-xs, y<-ys]
Functional programming 26
Haskell – Practical exercises
(4)1. Using list generators create a function that:
doubles all elements in a list; converts all small letters in String into capitals; which returns the list of divisors of a positive integer; Which check that a positive integer is a prime number.
2. Using list generators create functions than compute mathematical operations for sets (union, intersection, subset, complement).
3. Database implementation Consider data types:
type Person = Stringtype Book = Stringtype Database = [ (Person, Book)]
Create functions:books :: Database -> Person -> [Book]borrowers :: Database -> Book -> [Person]borroved :: Database -> Book -> BoolnumBorroved :: Database -> Book -> IntmakeLoan :: Database -> Person -> Book -> DatabasereturnLoan :: Database-> Person -> Book -> Database
Functional programming 27
Haskell – List functions in
Prelude (1)
elem 1 [2,3,4] = False
elem 2 [2,3,4] = True
elem 3 [] = False
elem _ [ ] = False
elem x (y:ys) | x == y = True
| otherwise = elem x ys
What is the type of the function elem?elem :: a -> [a] -> Bool - No, consider type classes…
Functional programming 28
Haskell – List functions in
Prelude (2)
Accessing list elements
head [1,2,3] = 1
tail [1,2,3] = [2,3]
last [1,2,3] = 3
init [1,2,3] = [1,2]
[1,2,3] !! 2 = 3
null [] = True
length [1,2,3] = 3
Functional programming 29
Haskell – List functions in
Prelude (3)
Merging lists
[1,2,3] ++ [4,5] = [1,2,3,4,5]
concat [[1,2],[3],[4,5]] = [1,2,3,4,5]
zip [1,2] [3,4,5] = [(1,3),(2,4)]
zipWith (+) [1,2] [3,4] = [4,6]
Computing with lists
sum [1,2,3,4] = 10
product [1,2,3,4] = 24
minimum [1,2,3,4] = 1
maximum [1,2,3,4] = 4
Functional programming 30
Haskell – List functions in
Prelude (4)
Taking part of a list take 3 [1,2,3,4,5] = [1,2,3]
drop 3 [1,2,3,4,5] = [4,5]
takeWhile (> 0) [1,3,0,4] = [1,3]
dropWhile (> 0) [1,3,0,4] = [0,4]
filter (>0) [1,3,0,2,-1] = [1,3,2]
Transforming a list reverse [1,2,3,4] = [4,3,2,1]
map (*2) [1,2,3] = [2,4,6]
Functional programming 31
Haskell – Practical exercises
(5) Consider following type representing picture:
type Pic = [String]
If you want to print this picture you can use:pp :: Pic -> IO ()
pp = putStr . concat . map (++"\n")
Picture example: obr :: Pic
obr = [ "....#....",
"...###...",
"..#.#.#..",
".#..#..#.",
"....#....",
"....#....",
"....#####"]
Create functions that: flips picture veriticaly and horizontaly;
place one picture above another (considering they have the same width);
place two pictures side by side (considering they have the same height);
rotate picture to the left and to the right.
Functional programming 32
Haskell – Local definition
Construction let ... in f x y = let p z = x + y +z
q = x – yin ( p 5 )* q
Construction where f x y = p * q
where p = x + yq = x - y
Functional programming 33
Haskell – Example
Example creating a list of squared numers dm [] = []dm (x:xs) = sq x : dm xs
where sq x = x * x
List’s ordering (quicksort) qs [] = []qs (x:xs) =
let ls = filter (< x) xsrs = filter (>=x) xs
in qs ls ++ [x] ++ qs rs
Functional programming 34
Haskell – Scope of local
definitions
maxsq x y
| sqx > sqy = sqx
| otherwise = sqy
where
sqx = sq x
sqy = sq y
sq :: Int -> Int
sq z = z*z
maxsq x y
| sq x > sq y = sq x
| otherwise = sq y
where
sq x = x * x
Functional programming 35
Haskell – Practical exercises
(6) Consider data in format:
type Name = String
type Price = Int
type BarCode = Int
type Database = [(BarCode, Name, Price)]
type TillType = [BarCode]
type BillType = [(Name,Price)]
Create functions that produce a nice bill from lists of bar codes. Define a function returning line length.makeBill :: TillType -> BillType
formatBill :: BillType -> String
produceBill :: TillType -> String
produceBill = formatBill. makeBill
Functional programming 36
Haskell – Pattern matching
(conclusion)
Patterns – guard expression, functions also case expressionfirstDigit :: String -> Char
firstDigit st = case (digit st) of
[] -> ’0’
(x:_) -> x
Summarized patterns a literal value – 1, ‘f’… a variable – x, y… a wildcard – ‘_’ a tupple pattern a constructor pattern – list, user defined type
Functional programming 37
Haskell – Example
Insert sortiSort :: [Int] -> [Int]
iSort [] = []
iSort (x:xs) = ins x (iSort xs) where
ins :: Int -> [Int] -> [Int]
ins x [] = [x]
ins x (y:ys)
| x <= y = x : (y:ys)
|otherwise = y : ins x ys
Functional programming 38
Haskell – Practical exercises
(7) Consider text in form:
In computer science, functional programming is a programming
paradigm that treats computation as the evaluation of mathematical functions
and avoids state and mutable data. It emphasizes the application of functions, in contrast to
the imperative
programming style, which emphasizes changes in state.
We want to get justified text in form:
Notes: whitespace = [‘\n’, ‘\t’, ‘ ‘]
lineLength = 30
In computer science, functional programming is a programming
paradigm that treats computation as the evaluation of mathematical
functions and avoids state and mutable data. It emphasizes the
application of functions, in contrast to the imperative programming style,
which emphasizes changes in state.
Functional programming 39
History – Language and
computer’s architecture
Languages are practically restricted by current hardware. Maybe a pitfall of functional languages in the past.
Von Neumann’s architecture Model of “classics” processors Give a background to some languages
Functional languages Backus (1978, Turing Adward) – criticism of a language
development based on a computer architecture Functional languages are better then imperative languages in some
cases. Prove program properties Easy to parallelize Base on algebraic rules
But, to work at least nearly as effective as imperative languages nontrivial optimizations must be performed. On the other hand, who cares about performance any more☺
Functional programming 40
Functional programming –
Summary - what we know yet
Imperative languages Program has a state.
We can modify a state using statements.
Statements are executed in given “order”.
Based on Von Neummans architecture - simple and effective integration.
Declarative languages No implicit state.
Program is composed from expressions not statements.
Programs describes what to compute and it does not defines how.
No execution order is given.
Functions are “first-class values”.
No side effects
Excellent abstraction mechanisms High order functions.
Function composition.
No variables.
Assignment has it “original” mathematical meaning
Basic technique is recursion – no cycles.
Functional programming 41
λ-calculus - History
1930 Alonzo Church Untyped λ-calculus
A formal system for function definition, function application and recursion. Functions are very crucial background of functional
languages.
Background for all functional languages.
The λ-calculus provides simple semantics for computation with functions so that properties of functional computation can be studied.
Functional programming 42
λ-calculus - Terms
Variables x, y, z, f, g, …
λ-abstraction (e is also a term) λ x . e
A Function with a parameter x and “body” e.
λ x y . e Equivalent to λ x . (λ y . e)
λ e . e (λ f x (f x x)) (λ f x (f x x))
Application (e1 e2)
Application of a function e1 on an argument e2
(f x y) Application of a function (f x) on an argument y Application of a function f on arguments x a y
Conventions of parentheses λx . λy . e1 e2 = (λx . (λy . e1 e2)) e1 e2 e3 = ((e1 e2) e3)
Functional programming 43
λ-calculus - Substitution
e1 [e2/x]
Replace all occurrences of free variable x in term
e1 with term e2
Substitution must be valid (free variable must not
be bound in e2 after the substitution)
(λ x y . f x y) [g z / f] = λ x y . (g z) x y
(λ x y . f x y) [g z / x] = λ x y . f x y
(λ x y . f x y) [g y / f] =invalid substitution
Functional programming 44
λ-calculus - Evaluation of
expressions (1)
α-reduction λ x . e ↔ λ y . e[ y / x ]
Renaming of a bound variable
Substitution must be valid
β-reduction (λ x . e1) e2 ↔ e1 [ e2 / x ]
“call a function“
η-reduction λ x . f x ↔ f
Removes “abstraction”
Variable x must not be free.
Functional programming 45
λ-calculus - Evaluation of
expressions (2) ((λ f x . f x x) (λ x y . p y x))
=β λ x . (λ x y . p y x) x x=α λ z . (λ x y . p y x) z z=β λ z . (λ y . p y z) z =β λ z . p z z
(λ f x . f x x) (λ x y . p y x)=η (λ f x . f x x) (λ y . p y)=η (λ f x . f x x) p=β λ x. p x x
Functional programming 46
λ-calculus - Evaluation of
expressions (3) redex --- reducible expression
α-redex, β-redex
Normal form Expression that contains no β-redex.
Church-Rosser theorem states that lambda calculus as a reduction system with lambda conversion rules satisfies the Church-Rosser property. If e1 ↔ e2, then there is e such that e1 → e and e2 → e.
Why is this important? Normal-order reduction is the evaluation strategy in which one continually
applies the rule for beta reduction in head position until no more such reductions are possible. At that point, the resulting term is in head normal form.
If a term has a head normal form, then normal order reduction will eventually reach it. In contrast, applicative order reduction may not terminate, even when the term has a
normal form.
Functional programming 47
λ-calculus - Evaluation of
expressions (4) Lambda calculus: normal form - no redex
Haskell: Practical aspects like:
If the result is a function, we do not need to reduce its „body“.
Usual forms: Normal form
Weak normal form
Weak head normal form
Reduction strategies When we combine a mechanism for choosing the next redex (innermost or
outermost) with a particular notion of normal form, we get a reduction strategy.
Significant reduction strategies Call by name: outermost reduction to weak head normal form
Normal order: outermost reduction to normal form
Call by value: innermost reduction to weak normal form
Applicative order: innermost reduction to normal form
Functional programming 48
λ-calculus - Evaluation of
expressions (5) Function f is strict when and only when: f ⊥ = ⊥
Non-strict functions are often called lazy.
Lazy evaluation Sub-expressions will be evaluated only when they are needed for
in evaluation.
Basic elements are:1. Arguments are evaluated only if they are needed.
2. Arguments are evaluated only once.
Add1 – solves normal order
Call by need As normal order, but function applications that would duplicate terms
instead name the argument, which is then reduced only "when it is needed“.
Non-strict evaluation
For functional languages it is lazy evaluation.
Functional programming 49
Functional languages -
Reasoning about programs (1)
Ok, functional languages have mathematical background, but is this any good for me (while I am a programmer)?
Consider possibility to reason about programs properties.
Mathematic induction (informally)a) Prove for n = 0 (base case)
b) On assumption that it holds for n, prove that it holds for n+1
Principle of structural induction for lists – we want to prove property P
a) Base case – prove P for [] outright.
b) Prove P (x:xs) on assumption that P(xs) holds.
Functional programming 50
Functional languages -
Reasoning about programs (2)
(xs ++ ys) ++ zs = xs ++ (ys ++ zs)
[] ++ ys = ys (++.1)
(x:xs) ++ ys = x: (xs ++ ys) (++.2)
a) [ ] => xs
([] ++ ys) ++ zs
= ys ++ zs (++.1)
= [] ++ (ys ++ zs) (++.1)
Functional programming 51
Functional languages -
Reasoning about programs (3)
(xs ++ ys) ++ zs = xs ++ (ys ++ zs)
[] ++ ys = ys (++.1)
(x:xs) ++ ys = x: (xs ++ ys) (++.2)
b) (x:xs) => xs((x:xs)++ys)++zs
= x:(xs++ys)++zs (++.2)
= x:((xs++ys)++zs) (++.2)
= x:(xs++(ys++zs)) (assumption)
= (x:xs)++(ys++zs) (++.2)
Functional programming 52
Functional languages -
Reasoning about programs (4)
length (xs++ys) = length xs + length ys
length [] = 0 (len.1)
length (_:xs) = 1 + length xs (len.2)
a) [] => xs
length ([] ++ ys)
= length ys (++.1)
= 0 + length ys (zero element for +)
= length [] + length ys (len.1)
Functional programming 53
Functional languages -
Reasoning about programs (5)
length (xs++ys) = length xs + length ys
length [] = 0 (len.1)
length (_:xs) = 1 + length xs (len.2)
b) (x:xs) => xslength ((x:xs) ++ ys)
= length (x:(xs++ys) (++.2)= 1 + length (xs++ys) (len.2)= 1 + (length xs + length ys) (assumption)= (1 + length xs) + length ys (associativity of +)= length (x:xs) + length ys (len.2)
Functional programming 54
Haskell – Functions as values
(revisited 1) Function can be argument, but functions can also be results of a
computation.
Functions composition (f . g) x= f (g x)
Composition is associative.
Consider order of operations: not . not True leads to an error!
Function as a result twice f = (f . f)
Partial applicationinc x = 1 + x
inc x = add 1 x
inc = add 1
inc = (+1) = (1+)
add = (+)
Point free programminglcaseString s = map toLower s
lcaseString = map toLower
Functional programming 55
Haskell – Functions as values
(revisited 2)
Lambda abstraction: \ x -> e … λx . einc = \x -> x+1
plus = \(x,y) -> x + y
dividers n = filter (\m -> n `mod` m == 0) [1..n]
Using lambda abstraction like a parameternonzero xs = filter p xs
where p x = x /= 0
nonzero xs = filter (/= 0) xs
nonzero xs = filter (\x -> x/=0) xs
Currying and uncurryingcurry :: ((a,b)->c) -> (a->b->c)
curry g x y = g (x,y)
uncurry :: (a->b->c) -> ((a,b)->c)
Uncurry f (x,y) = f x y
Functional programming 56
Haskell – Practical exercises
(8)
Consider text in form:In computer science, functional programming is a programming
paradigm that treats computation as the evaluation of mathematical
functions
and avoids state and mutable data. It emphasizes the application of
functions, in contrast to
the imperative
programming style, which emphasizes changes in state.
We want to automatically make an index. Only words at least 4 letters long will be indexed.
Words in index are alphabetically ordered.
Index will be a line number.
Notes: whitespace = [‘\n’, ‘\t’, ‘ ‘]
Functional programming 57
Haskell – Introducing classes (1)
Remember elem functionelem :: a->[a]->Bool
What is its type? Is it “ok”?
Defining type a classclass Eq a where
(==) :: a -> a -> Bool
Using type classeselem :: Eq a => a -> [a] -> Bool
What about the definition of ==? I need to compare bools, integers,… ?
Instances of type classesinstance Eq Bool where
True == True = True
False == False = True
_ == _ = False
Functional programming 58
Haskell – Introducing classes (2)
Default definitionsclass Eq a where
(==), (/=) :: a -> a -> Bool
x == y = not (x/=y)
x /= y = not (x == y)
Default definitions are overridden by instance definition.
At least one must be defined.
Derived classesclass Eq a => Ord a where
(<), (<=), (>), (>=) :: a -> a -> Bool
max, min :: a -> a -> a
compare :: a -> a -> Ordering
Class Ord inherits the operations from class Eq.
Functional programming 59
Haskell – Introducing classes (3)
User defined classesclass Visible a where
toString :: a -> String
size :: a -> Int
instance Visible Char where
toString ch = [ch]
size _ = 1
Instance Visible Bool where
toString True = “True”
toString False = “False”
size = length . toString
Defining contextinstance Visible a => Visible [a] where
toString = concat . map toString
size = foldr (+) 0 . map size
Multiple constrainsvSort :: (Ord a, Visible a) => [a] -> String
class (Ord a, Visible a) => OrdVisible a where
Functional programming 60
Haskell – Basic type classes
(1)
Eq a (==), (/=)
Eq a => Ord a (<), (<=), (>), (>=), min, max
Enum a succ, pred
Read a readsPrec
Show a showsPres, show
(Eq a, Show a) => Num a (+), (-), (*), negate, abs
(Num a) => Fractional a (/), recip
(Fractional a) => Floating a pi, exp, log, sqrt, (**), …
Functional programming 61
Haskell – Basic type classes (2)
Functional programming 62
Haskell – Show
Values convertible to “text” type ShowS = String -> Stringclass Show a where
showsPrec :: Int -> a -> ShowSshow :: a -> StringshowList :: [a] -> ShowS
showPoint :: Point -> StringshowPoint (Pt x,y) =
“(“ ++ show x ++ ”;” ++ show y ++ ”)”
instance Show Point whereshow p = showPoint p
Functional programming 63
Haskell – Practical exercises
(9)
Define class Visible.
Define “visibility” for tuples.
Make “visible objects” usable with function show.
Functional programming 64
Haskell – Algebraic types (1)
data Color = Red | Green | Blue
Color – type constructor
Red / Green / Blue – data constructor, nullaryconstructor
data Point = Point Float Float dist (Point x1 y1) (Point x2 y2) =
sqrt ((x2-x1)**2 + (y2-y1)**2)
dist (Point 1.0 2.0) (Point 4.0 5.0) = 5.0
data Point a = Point a a polymorphism
Constructor: Point :: a -> a -> Point aFunctional programming 65
Haskell – Algebraic types (2)
Recurrent data structuresdata List a = Null
| Cons a (List a)
lst :: List Intlst = Cons 1 (Cons 2 (Cons 3 Null))
append Null ys = ysappend (Cons x xs) ys =
Cons x (append xs ys)
Deriving instances of classdata Shape = Circle Float |
Rectangle Float Float
driving (Eq, Ord, Show)
Functional programming 66
Haskell – Algebraic types (3)
Example: Tree
data Tree1 a = Leaf a| Branch (Tree1 a) (Tree1 a)
data Tree2 a = Leaf a| Branch a (Tree2 a) (Tree2 a)
data Tree3 a = Null| Branch a (Tree3 a) (Tree3 a)
t2l (Leaf x) = [x]t2l (Branch lt rt) = (t2l lt) ++ (t2l rt)
Functional programming 67
Haskell – Practical exercises
(10) Consider following representation of expressions
data Expr = Num Int
| Add Expr Expr
| Sub Expr Expr
| Mul Expr Expr
| Div Expr Expr
| Var Char
deriving (Eq)
1. Create function eval that evaluates expresions.
2. Create function showExpr that shows expression as a String.
3. Extend class Show to be usable with our expressions.
4. Create function derivation representing symbolic derivation of a given expression.
Functional programming 68
Haskell – Abstract Data Type
Modules module A where -- A.hs, A.lhs
All definitions are visible.
Import module A where
import B
All visible definitions are imported.
Restricted exportu module Expr ( printExpr, Expr(..) ) where
Expr(..) – exports also constructorsExpr - exports data type name only
Restricted import import Expr hiding( printExpr )
import qualified Expr -- Expr.printExpr
import Expr as Vyraz -- Vyraz.printExpr
Functional programming 69
Haskell – ADT Queue (1)
Initialization: emptyQ
Test if queue is empty: isEmptyQ
Inserting new element at the end: addQ
Removing element from the beginning: remQ
module Queue
( Queue,
emptyQ, -- Queue a
isEmptyQ, -- Queue a -> Bool
addQ, -- a -> Queue a -> Queue a
remQ -- Queue q -> (a, Queue a)
) where
Functional programming 70
Haskell – ADT Queue (2)
newtype Queue a = Qu [a]
emptyQ = Qu []
isEmptyQ (Qu q) = empty q
addQ x (Qu xs) = Qu (xs++[x])
remQ q@(Qu xs)
| not (isEmptyQ q) = (head xs, Qu (tail xs))
| otherwise = error “remQ”
Functional programming 71
Haskell – ADT Queue (2)
-- diferent possibility for implementation
(reverse order in data representation)
addQ x (Qu xs) = Qu (x:xs)
remQ q@(Qu xs)
| not (isEmptyQ q) = (last xs, Qu (init xs))
| otherwise = error “remQ”
Consider complexity!
Functional programming 72
Haskell – Practical exercises (11)
Create abstract data type Stack push :: a -> Stack a -> Stack a
pop :: Stack a -> Stack a
top :: Stack a -> a
isEmpty :: Stack a ->Bool
Functional programming 73
Haskell – Lazy programming (1)
(remainder)
Function f is strict when and only when: f ⊥ = ⊥ Non-strict functions are often called lazy.
Lazy evaluation Sub-expressions will be evaluated only when they are needed for in
evaluation.
Basic elements are:1. Arguments are evaluated only if they are needed.
2. Arguments are evaluated only once.
Add1 – solves normal order
Call by need As normal order, but function applications that would duplicate terms
instead name the argument, which is then reduced only "when it is needed“.
Non-strict evaluation
For functional languages it is lazy evaluation.
Functional programming 74
Haskell – Lazy programming (2)
Data oriented programming Programming where complex data structures are constructed
and manipulated.
Example:1. Build a list of numbers 1 .. N
2. Take a power of each number.
3. Find the sum of the list.
Solution solve n = sum (map (^4) [1..n])
How does the calculation proceed?
Conclusion None of the intermediate lists is created!
Functional programming 75
Haskell – Programming with
actions (1)
Functional program consists of a list of definitions.
What about input? Consider function returning int.
inputInt :: Int
What will be a result of:inputDiff = inputInt – InputInt
funny :: Int-> Int
funny n = inputInt + n
When thinking about I/O it makes more sense to think about actions happening in sequence.
Actions in Haskell Type: IO a
Functional programming 76
Haskell – Programming with
actions (2)
Read / Write character getChar :: IO Char
putChar :: Char -> IO ()
One value type () – significat is their I/O action no the result.
Transforming value to a I/O action return :: a -> IO a
Notation: do It is used to sequence I/O actions
It is used to capture values returned by actions. ready :: IO Bool
ready = do c <- getCharreturn (c == ‘y’)
Variables here do not change values, single assignment only!
Functional programming 77
Haskell – Programming with
actions (3)
ExampleisEOF :: IO Bool
while :: IO Bool -> IO () -> IO ()
while test action
= do res <- test
if res then do action
while test action
else return ()
copyInputToOutput :: IO ()
copyInputToOutput
= while (do res <-isEOF
return (not res))
(do line <- getLine
putStr line)
Functional programming 78
Haskell – Programming with
actions – revisited (1)
What is a monad?
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
m >> k = m >>= \_ -> k
return :: a -> m a
fail :: String -> m a
fail s = error s
Functional programming 79
Haskell – Programming with
actions – revisited (2)
Tree
data Tree a = Nil | Node a (Tree a) (Tree a)
Standard approach
sTree :: Tree Int -> Int
sTree Nil = 0
sTeee (Node n t1 t2) = n+ sTree t1 + sTree t2
Monadic approach
sumTree :: Tree Int -> St Int
sumTree Nil = return 0
sumTree (Node n t1 t2) = do num <-return n
s1 <- sumTree t1
s2 <- sumTree t2
return (num+s1+s2)
Functional programming 80
Haskell – Programming with
actions – revisited (2)
Identity monad
data Id a = Id a
instance Monad Id where
return = Id
(>>=) (Id x) f = f x
Extracting value from identity monad
extract :: Id a -> a
extract (Id x) = x
Functional programming 81
Haskell – Main function
Starts the computation
Action returning nothing.
main :: IO ()main = do c <- getChar
putChar c
Functional programming 82
Haskell – Using actions – printing
a string
We can apply a function putStr to every
character.
map putChar xs
What will be a result type? map :: (a -> b) -> [a] -> [b]
putChar :: Char -> IO ()map putChar s :: [IO ()]
Transforming into single action
sequence :: [IO()] -> IO ()putStr :: String -> IO ()putStr s = sequence (map putChar s)
Functional programming 83
Haskell – Exceptions (1)
Exceptions are instances of type IOError There is XXX function for every exception.
isXXX :: IOError -> Bool isEOFError
isDoesNotExistError
Throwing exception: function failfail :: IOError -> IO a Results type is based on context.
Catching exceptions: finction catchcatch :: IO a -> (IOError -> IO a) -> IO a
1. First parameter is performed action.
2. Exceptions handler – it is performed if the exception is thrown.
3. The result is first parameter if exception was not throwen.Functional programming 84
Haskell – Exceptions (2)
Function getChar ignoring all exceptionsgetChar’ = getChar `catch`
( \ _ -> return ‘\n’ )
Function getChar handling EOF exception.getChar’ = getChar `catch` eofHandler
where eofHandler e =if isEOFError e
then return ‘\n’else fail e
Functional programming 85
Haskell – Working with files
(1)
type FilePath = String
data IOMode = ReadMode | WriteMode
| AppendMode | ReadWriteMode
data Handle
openFile :: FilePath -> IOMode -> IO Handle
hClose :: Handle -> IO ()
Functional programming 86
Haskell – Working with files (2)
stdin, stdout, stderr :: Handle
hGetChar :: Handle -> IO Char
getChar = hGetChar stdin
Functions starting with ‘h’ are using handlers.
hGetContents :: Handle -> String
Read a whole content.
Functional programming 87
Haskell – Working with files
(3)
import IO
main = do hin <- opf “From: “ ReadMode
hout <- opf “To: “ WriteMode
contents <- hGetContents hin
hPutStr hout contents
hClose hout
putStr “Done.”
opf :: String -> IOMode -> IO Handle
opf prompt mode = do putStr prompt
name <- getLine
openFile name mode
Functional programming 88
Haskell – Working with files
(3)
Function opf opens a file. If it can not be opened
then it prints a message.
opf prompt mode =do putStr prompt
name <- getLinecatch (openFile name mode)
(\_ -> do putStr (“Open error\n”)
opf prompt mode)
Functional programming 89
Haskell – Practical exercises
(12)
Create a program that reads a file and number
it’s lines.
1) Transform a text to linestext2lines :: String -> [String]
2) Numbers lines.numbering :: [String] -> [String]
3) Transforms a list of lines to one string
lines2text :: [String] -> String
(lines2text . numbering . text2lines) contents
Functional programming 90