Download presentation

Presentation is loading. Please wait.

Published byAlexis Jacobs Modified over 2 years ago

1
CS4026 Formal Models of Computation Part II The Logic Model Lecture 5 – Lists

2
formal models of computation 2 Lists Data structure for non-numeric programming. A sequence of any number of items. The items can be any Prolog term (including nested lists!). Useful when we dont know in advance how many items we are going to have. Flexible and generic. In Prolog, a list is represented as a sequence of terms, separated by commas and within […]: [123,hello,Var1,p(a,X),[1,2,3]]

3
formal models of computation 3 Types in lists: Haskell vs Prolog In Haskell, for every type t there is a type [t] for lists whose elements are of type t In Haskell, every list must have type [t] (for some t ), and hence all its elements must be of the same type So you cant for instance have a list, some of whose elements have type int and some of whose elements have type [int], e.g. [1,[2,3],4] Prolog places no restrictions on what elements of lists can be Less restrictive, but you lose the advantages of type checking

4
formal models of computation 4 Lists Lists are ordinary Prolog terms. The notation […] is just a shorthand: [1,2,3].(1,.(2,.(3,[]))) Lists are thus represented internally as trees: N.B.: the last element is always the empty list [] []..

5
formal models of computation 5 Lists Lists are recursively defined as: –The empty list []; or –A term followed by a list. Lists can enter queries: [].. ?- List = [1,2,3]. List = [1,2,3] yes ?-

6
formal models of computation 6 Lists (Contd) Prolog provides a notation for manipulating lists. The notation is [H|T], a shortand for.(H,T) –H stands for the first element of the list. –T stands for the remaining elements of the list and must be a list. We can build and decompose lists with [H|T] : ?- List = [1,2,3], List = [A|B]. A = 1, B = [2,3], List = [1,2,3] ?- List = [A|B], A = 1, B = [2,3]. A = 1, B = [2,3], List = [1,2,3]

7
formal models of computation 7 Lists (Contd) The [H|T] notation allows for variations: –[E1,E2|T] (a list with at least 2 elements) –[1|[2,3|T]] (a list [1,2,3|T] ) [H|T] is also a term, hence a tree: ?- List = [A|B], A = 1, B = [2,3]. A = 1, B = [2,3], List = [1,2,3] List AB. []

8
formal models of computation 8 Haskell vs Prolog list notations HaskellProlog [1,2,3] [] x:xs[X|Xs] or.(X,Xs) 1:2:xs[1,2|Xs]

9
formal models of computation 9 Operations on Lists We can access elements from the front of a list We can add elements to the front of a list: ?- L = [2,3], NewL = [1|L] L [] NewL

10
formal models of computation 10 Programming with Lists Because of their recursive definition, lists are naturally manipulated with recursive programs. Lets revisit our first loop program: –Enable it to build a list with values typed in loop(L):- % a loop to create a list L L = [X|Xs], % List L has form [X|Xs] read(X), % X is read from the standard Input (keyboard) X \= end, % if input different from end then loop(Xs). % build the tail recursively loop([]). % if input is end, then List is empty. ?- loop(MyList). |: a. |: b. |: end. MyList = [a,b] An argument is required to return the value of the list built

11
formal models of computation 11 Programming with Lists (Contd) Its execution: loop(L):- L = [X|Xs], read(X), X \= end, loop(Xs). loop([]). ?- loop(MyList). loop(L 1 ):- L 1 = [X 1 |Xs 1 ], read(X 1 ), X 1 \= end, loop(Xs 1 ). loop(L 2 ):- L 2 = [X 2 |Xs 2 ], read(X 2 ), X 2 \= end, loop(Xs 2 ). a L1L1 Xs 1 X1X1. b L2L2 Xs 2 X2X2. loop(L 3 ):- L 3 = [X 3 |Xs 3 ], read(X 3 ), X 3 \= end, loop(Xs 3 ). end L3L3 Xs 3 X3X3. loop(L 3 ):- L 3 = [X 3 |Xs 3 ], read(X 3 ), X 3 \= end, loop(Xs 3 ). ?- loop(MyList). |: a. ?- loop(MyList). |: a. |: b. ?- loop(MyList). |: a. |: b. |: end.

12
formal models of computation 12 Programming with Lists (Contd) Its execution: loop(L):- L = [X|Xs], read(X), X \= end, loop(Xs). loop([]). loop(L 1 ):- L 1 = [X 1 |Xs 1 ], read(X 1 ), X 1 \= end, loop(Xs 1 ). loop(L 2 ):- L 2 = [X 2 |Xs 2 ], read(X 2 ), X 2 \= end, loop(Xs 2 ). a L1L1 Xs 1 X1X1. b L2L2 Xs 2 X2X2. loop([]). [] ?- loop(MyList). |: a. |: b. |: end. ?- loop(MyList). |: a. |: b. |: end. MyList = [a,b]

13
formal models of computation 13 Programming with Lists (Contd) To check if an element appears in a list: –Check if element is the head; –Otherwise, check if element appears in tail This formulation is guaranteed to stop because lists are finite (!) and the process breaks list apart; In Prolog (first formulation): member(X,List):- % X is a member of List List = [Y|Ys], % if List is of form [Y|Ys] X = Y. % and X is equal to Y member(X,List):- % otherwise (if not as above) List = [Y|Ys], % break the list apart member(X,Ys). % and check if X appears in Ys

14
formal models of computation 14 Programming with Lists (Contd) Second formulation: member(X,[Y|Ys]):- % X is a member of [Y|Ys] X = Y. % if X is equal to Y member(X,[Y|Ys]):- % otherwise (if not as above) member(X,Ys). % check if X appears in Ys

15
formal models of computation 15 Programming with Lists (Contd) Third (final) formulation: General point: Uses of the built-in predicate = can almost always be replaced more elegantly with pattern-matching in the head of a clause. member(X,[X|_]). % X is member if it is head of list member(X,[_|Ys]):- % otherwise (if not as above) member(X,Ys). % check if X appears in Ys

16
formal models of computation 16 Prolog vs Haskell Cf Haskell member :: a -> [a] -> Bool member x [] = False member x (y:ys) = (x==y) || (member x ys) Note: [] case member(X,[X|_]). member(X,[_|Ys]) :- member(X,Ys).

17
formal models of computation 17 Programming with Lists (Contd) Lets run the previous program: member(X,[X|_]). member(X,[_|Ys]):- member(X,Ys). ?- member(3,[1,2,3]). The query member(3,[1,2,3]) does not match the 1 st clause!! Prolog matches member(3,[1,2,3]) with head of 2 nd clause: member(X 1,[_|Ys 1 ]):- member(X 1,Ys 1 ) We thus get the values for the variables: { X 1 /3, Ys 1 /[2,3] } Prolog now tries to prove member(X 1,Ys 1 ) that is member(3,[2,3]) The goal member(3,[2,3]) does not match the 1 st clause!! Prolog matches member(3,[2,3]) with head of 2 nd clause: member(X 2,[_|Ys 2 ]):- member(X 2,Ys 2 ) We thus get the values for the variables: { X 2 /3, Ys 2 /[3] } Prolog now tries to prove member(X 2,Ys 2 ) that is member(3,[3]) The query member(3,[3]) matches the 1 st clause!! ?- member(3,[1,2,3]). yes ?-

18
formal models of computation 18 Programming with Lists (Contd) Member program can be run in two ways: 1.To check if an element occurs in a list; 2.To obtain the elements of a list, one at a time It depends on the query – the program is exactly the same!! To obtain the elements of a list, we query: member(Elem,[1,2,3]) –We then get in Elem, the different elements ?- member(Elem,[1,2,3]). Elem = 1 ? ?- member(Elem,[1,2,3]). Elem = 1 ? ; Elem = 2 ? ?- member(Elem,[1,2,3]). Elem = 1 ? ; Elem = 2 ? ; Elem = 3 ? ?- member(Elem,[1,2,3]). Elem = 1 ? ; Elem = 2 ? ; Elem = 3 ? ; no ?- Can you trace this query?

19
formal models of computation 19 Ys [] a. b. Xs [] Zs Programming with Lists (Contd) To concatenate two lists Xs and Ys: –Create a 3 rd list Zs by copying all elements of Xs, –When we get to the end of Xs, put Ys as the tail of Zs Diagrammatically: 1 2..

20
formal models of computation 20 Programming with Lists (Contd) We need a predicate with 3 arguments: –1 st argument is the list Xs –2 nd argument is the list Ys –3 rd argument is the concatenation Xs. Ys (in this order) The first list Xs will control the loop As the first list Xs is traversed, its elements are copied onto the 3 rd argument (the concatenation). When we get an empty list, we stop and make Ys the value of the 3 rd argument

21
formal models of computation 21 Programming with Lists (Contd) First attempt: A more compact format: append([],Ys,Zs):- % if Xs is empty, Zs = Ys. % then Zs is Ys append([X|Xs],Ys,[Z|Zs]):- % otherwise X = Z, % copy X onto 3 rd argument append(Xs,Ys,Zs). % carry on recursively append([],Ys,Ys). % if Xs empty, then Zs is Ys append([X|Xs],Ys,[X|Zs]):- % else copy X onto 3 rd arg. append(Xs,Ys,Zs). % carry on recursively

22
formal models of computation 22 Programming with Lists (Contd) Execution: append([],Ys,Ys). append([X|Xs],Ys,[X|Zs]):- append(Xs,Ys,Zs). ?- append([1,2],[a,b],Res). append([X 1 |Xs 1 ],Ys 1,[X 1 |Zs 1 ]):- append(Xs 1,Ys 1,Zs 1 ). append([X 1 |Xs 1 ],Ys 1,[X 1 |Zs 1 ]):- append(Xs 1,Ys 1,Zs 1 ). {X 1 /1,Xs 1 /[2],Ys 1 /[a,b]} append([X 1 |Xs 1 ],Ys 1,[X 1 |Zs 1 ]):- append(Xs 1,Ys 1,Zs 1 ). {X 1 /1,Xs 1 /[2],Ys 1 /[a,b]} append([X 2 |Xs 2 ],Ys 2,[X 2 |Zs 2 ]):- append(Xs 2,Ys 2,Zs 2 ). append([X 2 |Xs 2 ],Ys 2,[X 2 |Zs 2 ]):- append(Xs 2,Ys 2,Zs 2 ). {X 2 /2,Xs 2 /[],Ys 2 /[a,b]} append([X 2 |Xs 2 ],Ys 2,[X 2 |Zs 2 ]):- append(Xs 2,Ys 2,Zs 2 ). {X 2 /2,Xs 2 /[],Ys 2 /[a,b]} aliasing: Zs 1 /[X 2 |Zs 2 ] append([],Ys 3,Ys 3 ). {Ys 3 /[a,b]} aliasing: Zs 2 /Ys 3 ?- append([1,2],[a,b],Res). Res = [1,2,a,b] ? yes ?- aliasing: Res/[X 1 |Zs 1 ]

23
formal models of computation 23 Programming with Lists (Contd) Execution: append([],Ys,Ys). append([X|Xs],Ys,[X|Zs]):- append(Xs,Ys,Zs). append([X 2 |Xs 2 ],Ys 2,[X 2 |Zs 2 ]):- append(Xs 2,Ys 2,Zs 2 ). {X 2 /2,Xs 2 /[],Ys 2 /[a,b]} append([X 1 |Xs 1 ],Ys 1,[X 1 |Zs 1 ]):- append(Xs 1,Ys 1,Zs 1 ). {X 1 /1,Xs 1 /[2],Ys 1 /[a,b]} append([],Ys 3,Ys 3 ). {Ys 3 /[a,b]} ?- append([1,2],[a,b],Res). Res = [1,2,a,b] ? yes ?- 1 Res Zs 1 X1X1. 2 Zs 2 X2X2. a. b. []

24
formal models of computation 24 Reversible definitions in Prolog As with member, append can be used in different ways, e.g. ?- append([a,b,c],[d],X). ?- append(X,[a,b,l,e],[e,a,t,a,b,l,e]). ?- append([e,a,t],X,[e,a,t,a,b,l,e]). ?- append(X,Y,[e,a,t,a,b,l,e]). Each of these would require a different function/method definition in Haskell/Java…

Similar presentations

© 2016 SlidePlayer.com Inc.

All rights reserved.

Ads by Google