09 Haskell Part 1 & 2 for Cook

advertisement
Programming Languages
Haskell
Dr. Philip Cannata
1
A programming language is a language with a welldefined syntax (lexicon and grammar), type system, and
semantics that can be used to implement a set of
algorithms.
Haskell
Dr. Philip Cannata
2
Haskell: /lusr/bin/hugs, should be in your default $PATH or for windows,
download and install winhugs at
http://cvs.haskell.org/Hugs/pages/downloading.htm
$ hugs
__ __ __ __ ____ ___ _________________________________________
|| || || || || || ||__ Hugs 98: Based on the Haskell 98 standard
||___|| ||__|| ||__|| __|| Copyright (c) 1994-2005
||---||
___||
World Wide Web: http://haskell.org/hugs
|| ||
Bugs: http://hackage.haskell.org/trac/hugs
|| || Version: 20051031
_________________________________________
Haskell 98 mode: Restart with command line option -98 to enable extensions
Type :? for help
Hugs> :load 09H1
Main>
Dr. Philip Cannata
To load the file “09H1.hs”
from the directory in
which you started hugs
3
Haskell
Expression
Dr. Philip Cannata
Hugs> 2 * 4 ^2
Number Expressions
32
Hugs> 8^2
64
Hugs> (2 * 4) ^ 2
64
Hugs> 2 + 4 ^ 2
18
Hugs> 2 ^ 200
1606938044258990275541962092341162602522202993782792835301376
Hugs> True && False
Boolean Expressions
False
Hugs> True || False
True
Hugs> 3 < 5
True
Hugs> 'c' < 'p'
Character Expressions
True
Hugs> 'c' > 'p'
False
Hugs> "tree" < "rock"
String Expressions
False
Hugs> "tree" > "rock"
True
4
Haskell
Basic Data
Structures
Hugs> ("dog", "cat", 5)
("dog","cat",5)
Tuples
Hugs> ["dog", "cat", 5]
ERROR - Cannot infer instance
*** Instance : Num [Char]
*** Expression : ["dog","cat",5]
Lists
Hugs> ["dog", "cat", "5"]
["dog","cat","5"]
Hugs> 1 : []
[1]
List Construction
Hugs> 1 : [2,3,4]
[1,2,3,4]
[expression | generator]
Hugs> [2 * x ^ 2 | x <- [1, 2, 3 ,4]]
[2,8,18,32]
List Comprehension
Hugs> [x * y | (x, y) <- [(1, 2), (3, 4), (5, 6)]]
[2,12,30]
Dr. Philip Cannata
5
Haskell
Basic Data
Structures
continued
List Comprehension
Cross product
Hugs> [(x, y) | x <- [1, 3 .. 6], y <- ['a', 'b', 'c', 'd']]
[(1,'a'),(1,'b'),(1,'c'),(1,'d'),(3,'a'),(3,'b'),(3,'c'),(3,'d'),(5,'a'),(5,'b'),(5,'c'),(5,'d')]
Hugs> [(x, y) | x <- [1..4], y <- [1..4]]
[(1,1),(1,2),(1,3),(1,4),(2,1),(2,2),(2,3),(2,4),(3,1),(3,2),(3,3),(3,4),(4,1),(4,2),
(4,3),(4,4)]
“<“ and “>” Relation
Hugs> [(x, y) | x <- [0..4], y <- [0..4], x < y]
[(0,1),(0,2),(0,3),(0,4),(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]
Hugs> [(x, y) | x <- [0..4], y <- [0..4], x > y]
[(1,0),(2,0),(2,1),(3,0),(3,1),(3,2),(4,0),(4,1),(4,2),(4,3)]
Hugs> [x | x <- [1..100], y <- [1..100], 72 == x * y]
[1,2,3,4,6,8,9,12,18,24,36,72]
Dr. Philip Cannata
Factors of 72
6
Haskell
Basic Data
Structures continued
Dr. Philip Cannata
List Comprehension
Database Query
Main> [empno | (empno, _, _, _, _, _, _) <- emp]
[7839,7698,7782,7566,7788,7902,7369,7499,7521,7654,7844,7876,7900,
7934]
Main> [empno | (empno, _, _, _, _, sal, _) <- emp, sal > 4000]
[7839]
Main> [empno | (empno, _, _, _, _, sal, _) <- emp, sal > 2000]
[7839,7698,7782,7566,7788,7902]
7
Haskell
Functions
Hugs> :type product
product :: Num a => [a] -> a
product Function
Hugs> product [ 2, 3, 4 ]
24
Hugs> product [ x | x <- [1..10]]
3628800
Hugs> :type (+)
(+) :: Num a => a -> a -> a
(+) Operator – an Operator is
a 2-ary Function
Hugs> 3 + 5
8
Hugs> (+) 3 5
8
Hugs> (\ x -> x ^ 2 + 4) 5
29
Dr. Philip Cannata
lambdas
8
Haskell
Pattern
Matching
Hugs> :type not
not :: Bool -> Bool
not :: Bool  Bool
not False = True
not True = False
Hugs> not True
False
Hugs> :type map
map :: (a -> b) -> [a] -> [b]
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
Hugs> map sqrt [ 1, 4, 9, 10 ]
[1.0,2.0,3.0,3.16227766016838]
Hugs> map (\ x -> x + 2) [ 1, 2, 3, 4]
[3,4,5,6]
Hugs> :type head
head :: [a] -> a
head :: [a] -> a
head = ( \(x:xs) -> x)
Hugs> head [5, 4, 3, 2, 1]
5
Dr. Philip Cannata
9
Haskell
Conditional
Expressions
Hugs> if True then 6 else 8
6
Hugs> if False then 6 else 8
8
not :: Bool  Bool
not False = True
not True = False
Let
Expressions
(i.e., local
variables)
Hugs> 2 + let x = sqrt 9 in (x + 1) * (x - 1)
10.0
Let assignment
assignment
.
.
.
in (expression)
Dr. Philip Cannata
10
Lazy Evaluation
v = 1/0
testLazy x = 2 + 10
testLazy1 x = 2 / x
Hugs> v
1.#INF
Hugs > testLazy 22
12
Hugs > testLazy v
12
Hugs > testLazy1 22
9.090909090909091e-2
Hugs > testLazy1 v
0.0
Hugs > (\x -> let y = x in (2 / y)) (1/0)
0.0
Hugs > (\x -> let y = x in (2 / y)) (0)
1.#INF
Dr. Philip Cannata
11
Propositional Logic
Propositions:
Statements that can be either True or False
Logical Operators:
• Negation: not
not :: Bool-> Bool
not True = False
not False = True
• Conjunction: &&
(&&) :: Bool-> Bool-> Bool
False && x = False
True && x = x
• Disjunction: ||
(||) :: Bool-> Bool-> Bool
True || x = True
False || x = x
Dr. Philip Cannata
Logical Operators:
• Implication (if – then): ==>
Antecedent ==> Consequent
(==>) :: Bool -> Bool -> Bool
x ==> y = (not x) || y
• Equivalence (if, and only if): <=>
(<=>) :: Bool -> Bool -> Bool
x <=> y = x == y
• Not Equivalent <+>
(<+>) :: Bool -> Bool -> Bool
x <+> y = x /= y
12
Truth tables:
P && Q
P || Q
not P
P ==> Q
P <=> Q
P <+> Q
P
Q
False
False
False
P
Q
P || Q
False
False
False
False
True
False
False
True
True
True
False
False
True
False
True
True
True
True
True
True
True
P
False
False
True
True
Q
PQ
False True
True True
False False
True True
P
P
False
True
True
False
P
Dr. Philip Cannata
Q
P && Q
P<=>Q
P
Q
P <+> Q
False
False
True
False
False
False
False
True
False
False
True
True
True
False
False
True
False
True
True
True
True
True
True
False
13
Reasoning with Truth Tables
Proposition (WFF): ((P  Q)((P)Q))
(P  Q)
(P)
False False
False
True
False
False
False True
True
True
True
True
True
False
True
False
True
True
True
True
True
False
True
True
P
Q
If prop is True when all
variables are True:
P, Q
((PQ)((P)Q))
((P)Q)
((PQ)((P)Q))
Some True: prop is Satisfiable*
If they were all True: Valid / Tautology
A Truth
double turnstile
All False: Contradiction
(not satisfiable*)
*Satisfiability was the first known NP-complete problem
Dr. Philip Cannata
14
Truth Table Application
truthTable :: (Bool -> Bool -> Bool) -> [Bool]
truthTable wff = [ (wff p q) | p <- [True,False],
q <- [True,False]]
tt = (\ p q -> not (p ==> q))
Hugs> :load 10Logic.hs
LOGIC> :type tt
tt :: Bool -> Bool -> Bool
LOGIC> truthTable tt
[False,True,False,False]
LOGIC> or (truthTable tt)
True
LOGIC> and (truthTable tt)
False
Dr. Philip Cannata
15
Satisfiable:
Are there well formed propositional formulas that return True for some input?
satisfiable1 :: (Bool -> Bool) -> Bool
satisfiable1 wff = (wff True) || (wff False)
satisfiable2 :: (Bool -> Bool -> Bool) -> Bool
satisfiable2 wff = or [ (wff p q) | p <- [True,False],
q <- [True,False]]
satisfiable3 :: (Bool -> Bool -> Bool -> Bool) -> Bool
satisfiable3 wff = or [ (wff p q r) | p <- [True,False],
q <- [True,False],
r <- [True,False]]
Define these first
infix 1 ==>
(==>) :: Bool -> Bool -> Bool
x ==> y = (not x) || y
infix 1 <=>
(<=>) :: Bool -> Bool -> Bool
x <=> y = x == y
infixr 2 <+>
(<+>) :: Bool -> Bool -> Bool
x <+> y = x /= y
( \ p -> not p)
( \ p q -> (not p) || (not q) )
( \ p q r -> (not p) || (not q) && (not r) )
Dr. Philip Cannata
16
Validity (Tautology):
Are there well formed propositional formulas that return True no matter what their
input values are?
valid1 :: (Bool -> Bool) -> Bool
valid1 wff = (wff True) && (wff False)
valid2 :: (Bool -> Bool -> Bool) -> Bool
valid2 wff = (wff True True)
&& (wff True False)
&& (wff False True)
&& (wff False False)
( \ p -> p || not p ) -- Excluded Middle
( \ p -> p ==> p )
( \ p q -> p ==> (q ==> p) )
( \ p q -> (p ==> q) ==> p )
Dr. Philip Cannata
17
Contradiction (Not Satisfiable):
Are there well formed propositional formulas that return False no matter what
their input values are?
contradiction1 :: (Bool -> Bool) -> Bool
contradiction1 wff = not (wff True) && not (wff False)
contradiction2 :: (Bool -> Bool -> Bool) -> Bool
contradiction2 wff = and [not (wff p q) | p <- [True,False],
q <- [True,False]]
contradiction3 :: (Bool -> Bool -> Bool -> Bool) -> Bool
contradiction3 wff = and [ not (wff p q r) | p <- [True,False],
q <- [True,False],
r <- [True,False]]
( \ p -> p && not p)
( \ p q -> (p && not p) || (q && not q) )
( \ p q r -> (p && not p) || (q && not q) && (r && not r) )
Dr. Philip Cannata
18
Truth:
Are there well formed propositional formulas that return True when their input is
True
truth1 :: (Bool -> Bool) -> Bool
truth1 wff = (wff True)
truth2 :: (Bool -> Bool -> Bool) -> Bool
truth2 wff = (wff True True)
( \ p -> not p)
( \ p q -> (p && q) || (not p ==> q))
( \ p q -> not p ==> q)
( \ p q -> (not p && q) && (not p ==> q) )
Dr. Philip Cannata
19
Equivalence:
logEquiv1 :: (Bool -> Bool) -> (Bool -> Bool) -> Bool
logEquiv1 bf1 bf2 =
(bf1 True <=> bf2 True) && (bf1 False <=> bf2 False)
logEquiv2 :: (Bool -> Bool -> Bool) -> (Bool -> Bool -> Bool) -> Bool
logEquiv2 bf1 bf2 =
and [(bf1 r s) <=> (bf2 r s) | r <- [True,False],
s <- [True,False]]
logEquiv3 :: (Bool -> Bool -> Bool -> Bool) -> (Bool -> Bool -> Bool -> Bool) -> Bool
logEquiv3 bf1 bf2 =
and [(bf1 r s t) <=> (bf2 r s t) | r <- [True,False],
s <- [True,False],
t <- [True,False]]
formula3 p q = p
formula4 p q = (p <+> q) <+> q
formula5 p q = p <=> ((p <+> q) <+> q)
*Haskell> logEquiv2 formula3 formula4
True
*Haskell> logEquiv2 formula4 formula5
False
Dr. Philip Cannata
20
Equivalence continued:
logEquiv1 id (\ p -> not (not p))
logEquiv1 id (\ p -> p && p)
logEquiv1 id (\ p -> p || p)
logEquiv2 (\ p q -> p ==> q) (\ p q -> not p || q)
logEquiv2 (\ p q -> not (p ==> q)) (\ p q -> p && not q)
logEquiv2 (\ p q -> not p ==> not q) (\ p q -> q ==> p)
logEquiv2 (\ p q -> p ==> not q) (\ p q -> q ==> not p)
logEquiv2 (\ p q -> not p ==> q) (\ p q -> not q ==> p)
logEquiv2 (\ p q -> p <=> q) (\ p q -> (p ==> q) && (q ==> p))
logEquiv2 (\ p q -> p <=> q) (\ p q -> (p && q) || (not p && not q))
logEquiv2 (\ p q -> p && q) (\ p q -> q && p)
logEquiv2 (\ p q -> p || q) (\ p q -> q || p)
logEquiv2 (\ p q -> not (p && q)) (\ p q -> not p || not q)
logEquiv2 (\ p q -> not (p || q)) (\ p q -> not p && not q)
logEquiv3 (\ p q r -> p && (q && r)) (\ p q r -> (p && q) && r)
logEquiv3 (\ p q r -> p || (q || r)) (\ p q r -> (p || q) || r)
logEquiv3 (\ p q r -> p && (q || r)) (\ p q r -> (p && q) || (p && r))
test9b logEquiv3 (\ p q r -> p || (q && r)) (\ p q r -> (p || q) && (p || r))
Dr. Philip Cannata
-- Idempotence
-- Idempotence
-- Implication
-- Contrapositive
-- Contrapositive
-- Contrapositive
-- Contrapositive
-- Commutativity
-- Commutativity
-- deMorgan
-- deMorgan
-- Associativity
-- Associativity
-- Distributivity
-- Distributivity
21
Why Reasoning with Truth Tables is Infeasible
Works fine when there are 2 variables
{T,F}  {T,F} = set of potential values of variables
2  2 lines in truth table
Three variables — starts to get tedious
{T,F}  {T,F}  {T,F} = set of potential values
2  2  2 lines in truth table
Twenty variables — definitely out of hand
2  2  …  2 lines (220)
You want to look at a million lines?
If you did, how would you avoid making errors?
Hundreds of variables — not in a million years
 A need for Predicate Logic. We’ll look at this with Prolog.
Dr. Philip Cannata
22
Haskell and SQL
Dr. Philip Cannata
23
Standard Oracle scott/tiger emp dept database
Dr. Philip Cannata
24
Standard Oracle scott/tiger emp dept database in Haskell
emp = [ (7839, "KING", "PRESIDENT", 0, "17-NOV-81", 5000, 10),
(7698, "BLAKE", "MANAGER", 7839, "01-MAY-81", 2850, 30),
(7782, "CLARK", "MANAGER", 7839, "09-JUN-81", 2450, 10),
(7566, "JONES", "MANAGER", 7839, "02-APR-81", 2975, 20),
(7788, "SCOTT", "ANALYST", 7566, "09-DEC-82", 3000, 20),
(7902, "FORD", "ANALYST", 7566, "03-DEC-81", 3000, 20),
(7369, "SMITH", "CLERK", 7902, "17-DEC-80", 800, 20),
(7499, "ALLEN", "SALESMAN", 7698, "20-FEB-81", 1600, 30),
(7521, "WARD", "SALESMAN", 7698, "22-FEB-81", 1250, 30),
(7654, "MARTIN", "SALESMAN", 7698, "28-SEP-81", 1250, 30),
(7844, "TURNER", "SALESMAN", 7698, "08-SEP-81", 1500, 30),
(7876, "ADAMS", "CLERK", 7788, "12-JAN-83", 1100, 20),
(7900, "JAMES", "CLERK", 7698, "03-DEC-81", 950, 30),
(7934, "MILLER", "CLERK", 7782, "23-JAN-82", 1300, 10) ]
dept = [ (10, "ACCOUNTING", "NEW YORK"),
(20, "RESEARCH", "DALLAS"),
(30, "SALES", "CHICAGO"),
(40, "OPERATIONS", "BOSTON") ]
Dr. Philip Cannata
25
Main>Main> [(empno, ename, job, sal, deptno) | (empno, ename, job, _, _, sal, deptno) <- emp]
[(7839,"KING","PRESIDENT",5000,10),
(7698,"BLAKE","MANAGER",2850,30),
(7782,"CLARK","MANAGER",2450,10),
(7566,"JONES","MANAGER",2975,20),
(7788,"SCOTT","ANALYST",3000,20),
(7902,"FORD","ANALYST",3000,20),
(7369,"SMITH","CLERK",800,20),
(7499,"ALLEN","SALESMAN",1600,30),
(7521,"WARD","SALESMAN",1250,30),
(7654,"MARTIN","SALESMAN",1250,30),
(7844,"TURNER","SALESMAN",1500,30),
(7876,"ADAMS","CLERK",1100,20),
(7900,"JAMES","CLERK",950,30),
(7934,"MILLER","CLERK",1300,10)]
Main>
Dr. Philip Cannata
26
Main> [(empno, ename, job, sal, deptno) | (empno, ename, job, _, _, sal, deptno) <- emp, deptno == 10]
[(7839,"KING","PRESIDENT",5000,10),
(7782,"CLARK","MANAGER",2450,10),
(7934,"MILLER","CLERK",1300,10)]
Main>
Dr. Philip Cannata
27
Main> [(empno, ename, job, sal, dname) | (empno, ename, job, _, _, sal, edeptno) <- emp, (deptno, dname, loc) <- dept, edeptno == deptno ]
[(7839,"KING","PRESIDENT",5000,"ACCOUNTING"),
(7698,"BLAKE","MANAGER",2850,"SALES"),
(7782,"CLARK","MANAGER",2450,"ACCOUNTING"),
(7566,"JONES","MANAGER",2975,"RESEARCH"),
(7788,"SCOTT","ANALYST",3000,"RESEARCH"),
(7902,"FORD","ANALYST",3000,"RESEARCH"),
(7369,"SMITH","CLERK",800,"RESEARCH"),
(7499,"ALLEN","SALESMAN",1600,"SALES"),
(7521,"WARD","SALESMAN",1250,"SALES"),
(7654,"MARTIN","SALESMAN",1250,"SALES"),
(7844,"TURNER","SALESMAN",1500,"SALES"),
(7876,"ADAMS","CLERK",1100,"RESEARCH"),
(7900,"JAMES","CLERK",950,"SALES"),
(7934,"MILLER","CLERK",1300,"ACCOUNTING")]
Main>
Dr. Philip Cannata
28
Main> length [sal | (_, _, _, _, _, sal, _) <- emp]
14
Main>
Main> (\y -> fromIntegral(sum y) / fromIntegral(length y)) ([sal | (_, _, _, _, _, sal, _) <- emp])
2073.21428571429
Main>
Dr. Philip Cannata
29
Main> map sqrt (map fromIntegral [sal | (_, _, _, _, _, sal, _) <- emp])
[70.7106781186548,
53.3853912601566,
49.4974746830583,
54.5435605731786,
54.7722557505166,
54.7722557505166,
28.2842712474619,
40.0,
35.3553390593274,
35.3553390593274,
38.7298334620742,
33.166247903554,
30.8220700148449,
36.0555127546399]
Main>
Dr. Philip Cannata
30
Main> (map sqrt
. map fromIntegral) [sal | (_, _, _, _, _, sal, _) <- emp]
[70.7106781186548,
53.3853912601566,
49.4974746830583,
54.5435605731786,
54.7722557505166,
54.7722557505166,
28.2842712474619,
40.0,
35.3553390593274,
35.3553390593274,
38.7298334620742,
33.166247903554,
30.8220700148449,
36.0555127546399]
Main>
Dr. Philip Cannata
31
Main> zip ([name | (_, name, _, _, _, _, _) <- emp]) (map sqrt (map fromIntegral [sal | (_, _, _, _, _, sal, _) <- emp]))
[("KING",70.7106781186548),
("BLAKE",53.3853912601566),
("CLARK",49.4974746830583),
("JONES",54.5435605731786),
("SCOTT",54.7722557505166),
("FORD",54.7722557505166),
("SMITH",28.2842712474619),
("ALLEN",40.0),
("WARD",35.3553390593274),
("MARTIN",35.3553390593274),
("TURNER",38.7298334620742),
("ADAMS",33.166247903554),
("JAMES",30.8220700148449),
("MILLER",36.0555127546399)]
Main>
Dr. Philip Cannata
32
Main> [(name, sal, dept) | (_, name, _, _, _, sal, dept) <- emp, dept `elem` [20, 30]]
[("BLAKE",2850,30),
("JONES",2975,20),
("SCOTT",3000,20),
("FORD",3000,20),
("SMITH",800,20),
("ALLEN",1600,30),
("WARD",1250,30),
("MARTIN",1250,30),
("TURNER",1500,30),
("ADAMS",1100,20),
("JAMES",950,30)]
Main>
Dr. Philip Cannata
33
Main> [(name, sal, dept) | (_, name, _, _, _, sal, dept) <- emp, dept `notElem` [20, 30]]
[("KING",5000,10),
("CLARK",2450,10),
("MILLER",1300,10)]
Main>
Dr. Philip Cannata
34
Main> [(name, sal, dept) | (_, name, _, _, _, sal, dept) <- emp, dept `notElem` [20, 30]] ++ [(name, sal, dept) | (_, name,
_, _, _, sal, dept) <- emp, dept `elem` [20, 30]]
[("KING",5000,10),
("CLARK",2450,10),
("MILLER",1300,10),
("BLAKE",2850,30),
("JONES",2975,20),
("SCOTT",3000,20),
("FORD",3000,20),
("SMITH",800,20),
("ALLEN",1600,30),
("WARD",1250,30),
("MARTIN",1250,30),
("TURNER",1500,30),
("ADAMS",1100,20),
("JAMES",950,30)]
Main>
Dr. Philip Cannata
35
Dr. Philip Cannata
36
Download