@@ -36,9 +36,29 @@ nth [_|Xs] N X :- N > 0
3636 & nth Xs {calc (N - 1 )} X.
3737
3838% 1.04
39- pred len o: list A, o: Int.
40- len [] 0 .
41- len [_| T] N :- N is {len T} + 1 .
39+ pred len o: list A, o: int.
40+ % `len Ls N` is true when `N` is the length of `Ls`.
41+ pred len.aux o: list A, o: int.
42+ % When `N` is bound, we count down from `N` to `0 `, removing one element of
43+ % `Ls` with each unit of `N` removed. If we arrive at `[]` and `0 ` at the
44+ % same time, we are done, and cannot possibly have more conclusions (thus the cut).
45+ len Ls N :- not (var N),
46+ ( len.aux [] 0
47+ & pi T M M' \
48+ len.aux [_|T] M :- M' is M - 1 ,
49+ len.aux T M'
50+ ) => len.aux Ls N, !.
51+ % When `N` is free, then we count up, starting from `0` to `N`, constructing
52+ % a list by adding a free variable to our list each time a unit is added to
53+ % `N`. When the list we' re constructing can be unified with the input `Ls`
54+ % then we' re at our `N`. If `Ls` is left partial in the tail, then we can
55+ % keep generating longer lists for `Ls` on backtracking.
56+ len Ls N :- var N,
57+ ( len.aux Ls N
58+ & pi L M M' \
59+ len.aux L M :- M' is M + 1,
60+ len.aux [_|L] M'
61+ ) => len.aux [] 0 .
4262
4363% 1.05
4464pred rev o: list A, o: list A.
0 commit comments