We consider the system Applicative_05__TreeFlatten. Alphabet: append : [a * a] --> a concat : [a] --> a cons : [a * a] --> a flatten : [] --> a -> a map : [a -> a * a] --> a nil : [] --> a node : [a * a] --> a Rules: map(f, nil) => nil map(f, cons(x, y)) => cons(f x, map(f, y)) flatten node(x, y) => cons(x, concat(map(flatten, y))) concat(nil) => nil concat(cons(x, y)) => append(x, concat(y)) append(nil, x) => x append(cons(x, y), z) => cons(x, append(y, z)) This AFS is converted to an AFSM simply by replacing all free variables by meta-variables (with arity 0). We use rule removal, following [Kop12, Theorem 2.23]. This gives the following requirements (possibly using Theorems 2.25 and 2.26 in [Kop12]): map(F, nil) >? nil map(F, cons(X, Y)) >? cons(F X, map(F, Y)) flatten node(X, Y) >? cons(X, concat(map(flatten, Y))) concat(nil) >? nil concat(cons(X, Y)) >? append(X, concat(Y)) append(nil, X) >? X append(cons(X, Y), Z) >? cons(X, append(Y, Z)) We use a recursive path ordering as defined in [Kop12, Chapter 5]. Argument functions: [[nil]] = _|_ We choose Lex = {} and Mul = {@_{o -> o}, append, concat, cons, flatten, map, node}, and the following precedence: node > flatten > concat > append > @_{o -> o} = map > cons Taking the argument function into account, and fixing the greater / greater equal choices, the constraints can be denoted as follows: map(F, _|_) > _|_ map(F, cons(X, Y)) >= cons(@_{o -> o}(F, X), map(F, Y)) @_{o -> o}(flatten, node(X, Y)) >= cons(X, concat(map(flatten, Y))) concat(_|_) >= _|_ concat(cons(X, Y)) >= append(X, concat(Y)) append(_|_, X) >= X append(cons(X, Y), Z) > cons(X, append(Y, Z)) With these choices, we have: 1] map(F, _|_) > _|_ because [2], by definition 2] map*(F, _|_) >= _|_ by (Bot) 3] map(F, cons(X, Y)) >= cons(@_{o -> o}(F, X), map(F, Y)) because [4], by (Star) 4] map*(F, cons(X, Y)) >= cons(@_{o -> o}(F, X), map(F, Y)) because map > cons, [5] and [10], by (Copy) 5] map*(F, cons(X, Y)) >= @_{o -> o}(F, X) because map = @_{o -> o}, map in Mul, [6] and [7], by (Stat) 6] F >= F by (Meta) 7] cons(X, Y) > X because [8], by definition 8] cons*(X, Y) >= X because [9], by (Select) 9] X >= X by (Meta) 10] map*(F, cons(X, Y)) >= map(F, Y) because map in Mul, [6] and [11], by (Stat) 11] cons(X, Y) > Y because [12], by definition 12] cons*(X, Y) >= Y because [13], by (Select) 13] Y >= Y by (Meta) 14] @_{o -> o}(flatten, node(X, Y)) >= cons(X, concat(map(flatten, Y))) because [15], by (Star) 15] @_{o -> o}*(flatten, node(X, Y)) >= cons(X, concat(map(flatten, Y))) because [16], by (Select) 16] flatten @_{o -> o}*(flatten, node(X, Y)) >= cons(X, concat(map(flatten, Y))) because [17] 17] flatten*(@_{o -> o}*(flatten, node(X, Y))) >= cons(X, concat(map(flatten, Y))) because flatten > cons, [18] and [23], by (Copy) 18] flatten*(@_{o -> o}*(flatten, node(X, Y))) >= X because [19], by (Select) 19] @_{o -> o}*(flatten, node(X, Y)) >= X because [20], by (Select) 20] node(X, Y) >= X because [21], by (Star) 21] node*(X, Y) >= X because [22], by (Select) 22] X >= X by (Meta) 23] flatten*(@_{o -> o}*(flatten, node(X, Y))) >= concat(map(flatten, Y)) because [24], by (Select) 24] @_{o -> o}*(flatten, node(X, Y)) >= concat(map(flatten, Y)) because [25], by (Select) 25] node(X, Y) >= concat(map(flatten, Y)) because [26], by (Star) 26] node*(X, Y) >= concat(map(flatten, Y)) because node > concat and [27], by (Copy) 27] node*(X, Y) >= map(flatten, Y) because node > map, [28] and [29], by (Copy) 28] node*(X, Y) >= flatten because node > flatten, by (Copy) 29] node*(X, Y) >= Y because [30], by (Select) 30] Y >= Y by (Meta) 31] concat(_|_) >= _|_ by (Bot) 32] concat(cons(X, Y)) >= append(X, concat(Y)) because [33], by (Star) 33] concat*(cons(X, Y)) >= append(X, concat(Y)) because concat > append, [34] and [38], by (Copy) 34] concat*(cons(X, Y)) >= X because [35], by (Select) 35] cons(X, Y) >= X because [36], by (Star) 36] cons*(X, Y) >= X because [37], by (Select) 37] X >= X by (Meta) 38] concat*(cons(X, Y)) >= concat(Y) because concat in Mul and [39], by (Stat) 39] cons(X, Y) > Y because [40], by definition 40] cons*(X, Y) >= Y because [41], by (Select) 41] Y >= Y by (Meta) 42] append(_|_, X) >= X because [43], by (Star) 43] append*(_|_, X) >= X because [44], by (Select) 44] X >= X by (Meta) 45] append(cons(X, Y), Z) > cons(X, append(Y, Z)) because [46], by definition 46] append*(cons(X, Y), Z) >= cons(X, append(Y, Z)) because append > cons, [47] and [51], by (Copy) 47] append*(cons(X, Y), Z) >= X because [48], by (Select) 48] cons(X, Y) >= X because [49], by (Star) 49] cons*(X, Y) >= X because [50], by (Select) 50] X >= X by (Meta) 51] append*(cons(X, Y), Z) >= append(Y, Z) because append in Mul, [52] and [55], by (Stat) 52] cons(X, Y) > Y because [53], by definition 53] cons*(X, Y) >= Y because [54], by (Select) 54] Y >= Y by (Meta) 55] Z >= Z by (Meta) We can thus remove the following rules: map(F, nil) => nil append(cons(X, Y), Z) => cons(X, append(Y, Z)) We use rule removal, following [Kop12, Theorem 2.23]. This gives the following requirements (possibly using Theorems 2.25 and 2.26 in [Kop12]): map(F, cons(X, Y)) >? cons(F X, map(F, Y)) flatten node(X, Y) >? cons(X, concat(map(flatten, Y))) concat(nil) >? nil concat(cons(X, Y)) >? append(X, concat(Y)) append(nil, X) >? X We use a recursive path ordering as defined in [Kop12, Chapter 5]. Argument functions: [[concat(x_1)]] = x_1 [[map(x_1, x_2)]] = map(x_2, x_1) We choose Lex = {map} and Mul = {@_{o -> o}, append, cons, flatten, nil, node}, and the following precedence: nil > node > map > cons > @_{o -> o} > flatten > append Taking the argument function into account, and fixing the greater / greater equal choices, the constraints can be denoted as follows: map(F, cons(X, Y)) > cons(@_{o -> o}(F, X), map(F, Y)) @_{o -> o}(flatten, node(X, Y)) >= cons(X, map(flatten, Y)) nil >= nil cons(X, Y) > append(X, Y) append(nil, X) > X With these choices, we have: 1] map(F, cons(X, Y)) > cons(@_{o -> o}(F, X), map(F, Y)) because [2], by definition 2] map*(F, cons(X, Y)) >= cons(@_{o -> o}(F, X), map(F, Y)) because map > cons, [3] and [10], by (Copy) 3] map*(F, cons(X, Y)) >= @_{o -> o}(F, X) because map > @_{o -> o}, [4] and [6], by (Copy) 4] map*(F, cons(X, Y)) >= F because [5], by (Select) 5] F >= F by (Meta) 6] map*(F, cons(X, Y)) >= X because [7], by (Select) 7] cons(X, Y) >= X because [8], by (Star) 8] cons*(X, Y) >= X because [9], by (Select) 9] X >= X by (Meta) 10] map*(F, cons(X, Y)) >= map(F, Y) because [11], [4] and [14], by (Stat) 11] cons(X, Y) > Y because [12], by definition 12] cons*(X, Y) >= Y because [13], by (Select) 13] Y >= Y by (Meta) 14] map*(F, cons(X, Y)) >= Y because [15], by (Select) 15] cons(X, Y) >= Y because [12], by (Star) 16] @_{o -> o}(flatten, node(X, Y)) >= cons(X, map(flatten, Y)) because [17], by (Star) 17] @_{o -> o}*(flatten, node(X, Y)) >= cons(X, map(flatten, Y)) because [18], by (Select) 18] node(X, Y) >= cons(X, map(flatten, Y)) because [19], by (Star) 19] node*(X, Y) >= cons(X, map(flatten, Y)) because node > cons, [20] and [22], by (Copy) 20] node*(X, Y) >= X because [21], by (Select) 21] X >= X by (Meta) 22] node*(X, Y) >= map(flatten, Y) because node > map, [23] and [24], by (Copy) 23] node*(X, Y) >= flatten because node > flatten, by (Copy) 24] node*(X, Y) >= Y because [25], by (Select) 25] Y >= Y by (Meta) 26] nil >= nil by (Fun) 27] cons(X, Y) > append(X, Y) because [28], by definition 28] cons*(X, Y) >= append(X, Y) because cons > append, [29] and [31], by (Copy) 29] cons*(X, Y) >= X because [30], by (Select) 30] X >= X by (Meta) 31] cons*(X, Y) >= Y because [32], by (Select) 32] Y >= Y by (Meta) 33] append(nil, X) > X because [34], by definition 34] append*(nil, X) >= X because [35], by (Select) 35] X >= X by (Meta) We can thus remove the following rules: map(F, cons(X, Y)) => cons(F X, map(F, Y)) concat(cons(X, Y)) => append(X, concat(Y)) append(nil, X) => X We use rule removal, following [Kop12, Theorem 2.23]. This gives the following requirements (possibly using Theorems 2.25 and 2.26 in [Kop12]): flatten node(X, Y) >? cons(X, concat(map(flatten, Y))) concat(nil) >? nil We use a recursive path ordering as defined in [Kop12, Chapter 5]. Argument functions: [[nil]] = _|_ We choose Lex = {} and Mul = {@_{o -> o}, concat, cons, flatten, map, node}, and the following precedence: @_{o -> o} > cons > concat > node > flatten > map Taking the argument function into account, and fixing the greater / greater equal choices, the constraints can be denoted as follows: @_{o -> o}(flatten, node(X, Y)) >= cons(X, concat(map(flatten, Y))) concat(_|_) > _|_ With these choices, we have: 1] @_{o -> o}(flatten, node(X, Y)) >= cons(X, concat(map(flatten, Y))) because [2], by (Star) 2] @_{o -> o}*(flatten, node(X, Y)) >= cons(X, concat(map(flatten, Y))) because @_{o -> o} > cons, [3] and [7], by (Copy) 3] @_{o -> o}*(flatten, node(X, Y)) >= X because [4], by (Select) 4] node(X, Y) >= X because [5], by (Star) 5] node*(X, Y) >= X because [6], by (Select) 6] X >= X by (Meta) 7] @_{o -> o}*(flatten, node(X, Y)) >= concat(map(flatten, Y)) because @_{o -> o} > concat and [8], by (Copy) 8] @_{o -> o}*(flatten, node(X, Y)) >= map(flatten, Y) because @_{o -> o} > map, [9] and [10], by (Copy) 9] @_{o -> o}*(flatten, node(X, Y)) >= flatten because @_{o -> o} > flatten, by (Copy) 10] @_{o -> o}*(flatten, node(X, Y)) >= Y because [11], by (Select) 11] node(X, Y) >= Y because [12], by (Star) 12] node*(X, Y) >= Y because [13], by (Select) 13] Y >= Y by (Meta) 14] concat(_|_) > _|_ because [15], by definition 15] concat*(_|_) >= _|_ by (Bot) We can thus remove the following rules: concat(nil) => nil We use rule removal, following [Kop12, Theorem 2.23]. This gives the following requirements (possibly using Theorems 2.25 and 2.26 in [Kop12]): flatten node(X, Y) >? cons(X, concat(map(flatten, Y))) We use a recursive path ordering as defined in [Kop12, Chapter 5]. Argument functions: [[concat(x_1)]] = x_1 [[flatten]] = _|_ We choose Lex = {} and Mul = {@_{o -> o}, cons, map, node}, and the following precedence: @_{o -> o} > cons > map > node Taking the argument function into account, and fixing the greater / greater equal choices, the constraints can be denoted as follows: @_{o -> o}(_|_, node(X, Y)) > cons(X, map(_|_, Y)) With these choices, we have: 1] @_{o -> o}(_|_, node(X, Y)) > cons(X, map(_|_, Y)) because [2], by definition 2] @_{o -> o}*(_|_, node(X, Y)) >= cons(X, map(_|_, Y)) because @_{o -> o} > cons, [3] and [7], by (Copy) 3] @_{o -> o}*(_|_, node(X, Y)) >= X because [4], by (Select) 4] node(X, Y) >= X because [5], by (Star) 5] node*(X, Y) >= X because [6], by (Select) 6] X >= X by (Meta) 7] @_{o -> o}*(_|_, node(X, Y)) >= map(_|_, Y) because @_{o -> o} > map, [8] and [9], by (Copy) 8] @_{o -> o}*(_|_, node(X, Y)) >= _|_ by (Bot) 9] @_{o -> o}*(_|_, node(X, Y)) >= Y because [10], by (Select) 10] node(X, Y) >= Y because [11], by (Star) 11] node*(X, Y) >= Y because [12], by (Select) 12] Y >= Y by (Meta) We can thus remove the following rules: flatten node(X, Y) => cons(X, concat(map(flatten, Y))) All rules were succesfully removed. Thus, termination of the original system has been reduced to termination of the beta-rule, which is well-known to hold. +++ Citations +++ [Kop12] C. Kop. Higher Order Termination. PhD Thesis, 2012.