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 PQ 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 ((PQ)((P)Q)) ((P)Q) ((PQ)((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