In the first part of the article about the Arend language, we examined the simplest inductive types, recursive functions, classes and sets.
2. Sorting Lists in Arend
2.1 Ordered Lists in Arend
We define the type of ordered lists as a pair consisting of a list and proof of its ordering. As we said before, in Arend, dependent pairs are defined using the 
\Sigma keyword. We will determine the type of 
Sorted by comparing with the sample, inspired by the definition from the already mentioned 
article about ordered lists. \func SortedList (O : LinearOrder.Dec) => \Sigma (l : List O) (Sorted l) \data Sorted {A : LinearOrder.Dec} (xs : List A) \elim xs | nil => nilSorted | :-: x nil => singletonSorted | :-: x1 (:-: x2 xs) => consSorted ((x1 = x2) || (x1 < x2)) (Sorted (x2 :-: xs)) 
Note: Arend was able to automatically infer that the 
Sorted type is contained in the 
\Prop universe. This happened because all three patterns in the 
Sorted definition are mutually exclusive, and the 
consSorted constructor has two parameters, both of which belong to 
\Prop .
Let us prove some obvious property of the 
Sorted predicate, say that the tail of an ordered list is itself an ordered list (this property will be useful to us in the future).
 \func tail-sorted {O : LinearOrder.Dec} (x : O) (xs : List O) (A : Sorted (x :-: xs)) : Sorted xs \elim xs, A | nil, _ => nilSorted | :-: _ _, consSorted _ xs-sorted => xs-sorted 
In the 
tail-sorted we used pattern matching on the 
xs list and the 
Sorted predicate at the same time, in addition, we used 
the skip symbol “_”, which can be substituted for unused variables.
One may ask if it is possible in Arend to prove the property of ordered lists, mentioned in section 1.3 as an example of a fact that cannot be proved in Agda without annotations of immateriality. Recall that this property states that to prove the equality of ordered lists defined through dependent pairs, it is sufficient to verify the equality of the first components of the pairs.
It is argued that in Arend this property is easily obtained as a consequence of the 
inProp construction already mentioned above and the extensionality property for dependent 
SigmaExt pairs.
 \func sorted-equality {A : LinearOrder.Dec} (l1 l2 : SortedList A) (P : l1.1 = l2.1) : l1 = l2 => SigmaPropExt Sorted l1 l2 P 
The 
SigmaPropExt property 
SigmaPropExt proved in the 
Paths module of the standard library, and many other facts from the second chapter 
of the HoTT book , including the 
property of functional extensionality , are also proved there.
The 
.n operator 
.n used in Arend to access the sigma type projector with number n (in our case, the sigma type is 
SortedList A , and the expression 
l1.1 means the first component of this type is an expression of type 
List A ).
2.2 Implementation of the “be permutation” property
Now let's try to implement the list sorting function on Arend. Naturally, we want to have not a simple implementation of the sorting algorithm, but an implementation together with a proof of some properties.
Clearly, this algorithm must have at least 2 properties:
1. The result of the algorithm should be an ordered list.
2. The resulting list should be a permutation of the original list.
First, let’s try to implement the “be permutation” property of lists on Arend. To do this, we adapt the definition taken 
from here for Arend.
 \truncated \data InsertSpec {A : \Set} (xs : List A) (a : A) (ys : List A) : \Prop \elim xs, ys | xs, :-: y ys => insertedHere (a = y) (xs = ys) | :-: x xs, :-: y ys => insertedThere (x = y) (InsertSpec xs a ys) \truncated \data Perm {A : \Set} (xs ys : List A) : \Prop | permInsert (xs' ys' : List A) (a : A) (Perm xs' ys') (InsertSpec xs' a xs) (InsertSpec ys' a ys) | permTrivial (xs = ys) 
The 
InsertSpec predicate introduced by us has the following intuitive meaning: 
InsertSpec xs a ys exactly means that the list 
ys is the result of inserting the element a inside the list 
xs (at any position). Thus, 
InsertSpec can be taken as a specification of the insert function.
Clearly, the 
Perm data type really defines the “be permutation” relationship: the 
permInsert constructor 
permInsert exactly that 
xs and 
ys are mutually permutable if 
xs and 
ys are obtained by inserting the same element a into some lists 
xs' and 
ys' shorter lengths, which are already permutations of each other.
For our definition of the “be permutation” property, it is easy to verify the symmetry property.
 \func Perm-symmetric {A : \Set} {xs ys : List A} (P : Perm xs ys) : Perm ys xs \elim P | permTrivial xs=ys => permTrivial (inv xs=ys) | permInsert perm-xs'-ys' xs-spec ys-spec => permInsert (Perm-symmetric perm-xs'-ys') ys-spec xs-spec 
The transitivity property is also fulfilled for 
Perm , however, its verification is much more complicated. Since this property does not play any role in the implementation of our sorting algorithm, we leave it to the reader as an exercise.
 \func Perm-transitive {A : \Set} (xs ys zs : List A) (P1 : Perm xs ys) (P2 : Perm ys zs) : Perm xs zs => {?} 
2.3 Change in homotopy levels when compared with the sample
Now let's try to implement a function that inserts an element into an ordered list so that the resulting list remains ordered. Let's start with the following naive implementation.
 \func insert {O : LinearOrder.Dec} (xs : List O) (y : O) : List O \elim xs | nil => y :-: nil | :-: x xs' => \case LinearOrder.trichotomy xy \with {  | byLeft x=y => x :-: insert xs' y  | byRight (byLeft x<y) => x :-: insert xs' y  | byRight (byRight y<x) => y :-: x :-: xs' } 
The 
\case construction allows matching with a sample of an arbitrary expression ( 
\elim can be used only at the highest level of a function definition and only for its parameters). If you ask Arend to check the 
insert type, the following error message will be displayed.
 [ERROR] Data type '||' is truncated to the universe \Prop  which does not fit in the universe of the eliminator type: List OE In: | byLeft x-leq-y => x :-: insert xs' y While processing: insert 
The problem is that in the 
LinearOrder.Dec class 
LinearOrder.Dec definition of 
trichotomy given using the 
|| operator , which, in turn, is determined using propositional truncation. As already mentioned, for types belonging to the 
\Prop universe, matching with a pattern in Arend is allowed only if the type of the resulting expression is itself an assertion (for the function above, the result is of type 
List OE , and this type is a set).
Is there any way around this problem? The easiest way to solve this is to change the definition of the property of trichotomy. Consider the following definition of trichotomy, using the un-truncated type 
Or instead of the truncated 
|| :
 \func set-trichotomy {A : StrictPoset} (xy : A) => ((x = y) `Or` (x < y)) `Or` (y < x) 
Does this definition 
trichotomy in anything from the original 
trichotomy definition through 
|| ? Why did we even use a propositionally truncated type if it only complicates our life and prevents us from using pattern matching?
Let's try to answer the first question for a start: for strict 
StrictPoset orders 
StrictPoset difference between 
trichotomy and 
set-trichotomy is actually not at all. Note that the 
set-trichotomy type is a statement. This fact follows from the fact that all three alternatives in the definition of trichotomy are mutually exclusive due to axioms of order, and each of the three types 
x = y, x < y, y < x is itself a statement ( 
x = y is a statement, so as in the definition of the 
BaseSet class 
BaseSet we demanded that the media 
E a set!).
 \func set-trichotomy-isProp {A : StrictPoset} (xy : A) (l1 l2 : set-trichotomy xy): l1 = l2 \elim l1, l2 | inl (inl l1), inl (inl l2) => pmap (\lam z => inl (inl z)) (Path.inProp l1 l2) | inl (inr l1), inl (inr l2) => pmap (\lam z => inl (inr z)) (Path.inProp l1 l2) | inr l1, inr l2 => pmap inr (Path.inProp l1 l2) | inl (inl l1), inl (inr l2) => absurd (lt-eq-false l1 l2) | inl (inr l1), inl (inl l2) => absurd (lt-eq-false l2 l1) | inl (inl l1), inr l2 => absurd (lt-eq-false (inv l1) l2) | inr l1, inl (inl l2) => absurd (lt-eq-false (inv l2) l1) | inl (inr l1), inr l2 => absurd (lt-lt-false l1 l2) | inr l1, inl (inr l2) => absurd (lt-lt-false l2 l1) \where {  \func lt-eq-false {A : StrictPoset} {xy : A} (l1 : x = y) (l2 : x < y) : Empty =>    A.<-irreflexive x (transport (x <) (inv l1) l2)  \func lt-lt-false {A : StrictPoset} {xy : A} (l1 : x < y) (l2 : y < x) : Empty =>   A.<-irreflexive x (A.<-transitive _ _ _ l1 l2) } 
In the listing above, 
absurd is the designation for the ex falso quodlibet principle, which is defined in the 
Logic module. Since the 
Empty type does not have constructors in the definition (see section 1.2), it is not necessary to go through cases in the definition of 
absurd :
 \func absurd {A : \Type} (x : Empty) : A 
Since we now know that 
set-trichotomy is a statement, we can derive the 
set-trichotomy property from the usual 
trichotomy property of decidable orders. To do this, we can use the 
\return \level construction, which tells the Arend timer that at this point the pattern matching is a permitted operation (we have to show proof that the result of the 
set-trichotomy-property function is a statement).
 \func set-trichotomy-property {A : LinearOrder.Dec} (xy : A) : set-trichotomy xy => \case A.trichotomy xy \return \level (set-trichotomy xy) (set-trichotomy-isProp xy) \with {  | byLeft x=y => inl (inl x=y)  | byRight (byLeft x<y) => inl (inr x<y)  | byRight (byRight y<x) => inr (y<x) } 
Let us now try to answer the second question, namely, why, when formulating the properties of mathematical objects, it is preferable to use not ordinary, but propositionally truncated constructions. Consider for this a fragment of the definition of non-strict linear orders (full definitions of 
Lattice and 
TotalOrder can be found in the 
LinearOrder module):
 \class TotalOrder \extends Lattice { | totality (xy : E) : x <= y || y <= x } 
Now let's try to 
TotalOrder how the meaning of the 
TotalOrder class would have changed if we had written the definition of the totality field through the un-truncated 
Or construction.
 \class BadTotalOrder \extends Lattice { | badTotality (xy : E) : (x <= y) `Or` (y <= x) } 
In this case, the type 
(x <= y) `Or` (y <= x) no longer a statement, because in case of equal values of 
x and 
y both alternatives in the definition of 
badTotality can be implemented, and the choice of the left or right branch in the proof of 
badTotality absolutely arbitrary and remains at the discretion of the user - there is no reason to prefer one 
Or constructor to another.
Now it’s clear what the difference between 
TotalOrder and 
BadTotalOrder . Two ordered sets 
O1 O2 : 
TotalOrder are always equal when it is possible to prove the equality of the sets 
O1.E, O2.E and the orders 
O1.<, O2.< Given on them (this is the desired property). On the other hand, for 
O1 O2 : 
BadTotalOrder it is 
BadTotalOrder to prove the equality of 
O1 and 
O2 only in cases where, in addition to all elements 
x from 
E equality 
O1.badTotality xx and 
O2.badTotality xx .
Thus, it turns out that the class 
BadTotalOrder intuitively needs to be considered not as a “linearly ordered set”, but as a “linearly ordered set together with the choice for each element 
x field 
E left or right branch 
Or in the implementation of 
badTotality xx ".
2.4 Sort Algorithm
We now proceed to implement the sorting algorithm. Let's try to fix the naive implementation of the 
insert function from the previous section using the proved 
set-trichotomy-property (in this case, due to the more successful arrangement of brackets in the definition of 
set-trichotomy , we have reduced the number of cases considered).
 \func insert {O : LinearOrder.Dec} (xs : List O) (y : O) : List O \elim xs | nil => y :-: nil | :-: x xs' => \case set-trichotomy-property xy \with {  | inr y<x => y :-: x :-: xs'  | inl x<=y => x :-: insert xs' y } 
Let us now try to implement an analog of this definition for ordered lists. We will use the special 
\let … \in construct, which allows us to add new local variables to the context.
 \func insert {O : LinearOrder.Dec} (xs : SortedList O) (y : O) : SortedList O \elim xs | (nil, _) => (y :-: nil, singletonSorted) | (:-: x xs', xs-sorted) => \case set-trichotomy-property xy \with {  | inr y<x => (y :-: x :-: xs', consSorted (byRight y<x) xs-sorted)  | inl x<=y => \let (result, result-sorted) => insert (xs', tail-sorted x xs' xs-sorted) y         \in (x :-: result, {?}) 
We left an incomplete fragment in the proof (indicated by the expression 
{?} ) In the place where we need to show that the list 
x :-: result ordered. Although in the context there is evidence of the ordering of the 
result list, it remains for us to verify that 
x does not exceed the value of the first element of the 
result list, which is not so easy to follow from the premises in the context (to see all the premises in the current target - this is what we call present branch of calculations - you need to request type checking from the 
insert function).
It turns out that 
insert much easier to implement if we prove the ordering of the resulting list in parallel with the proof of the 
insert specification. Change the signature of 
insert and write proof of this specification in the simplest cases:
 \func insert {O : LinearOrder.Dec} (xs : SortedList O) (y : O) : \Sigma (ys : SortedList O) (InsertSpec xs.1 y ys.1) \elim xs | (nil, _) => ((y :-: nil, singletonSorted), insertedHere idp idp) | (:-: x xs', xs-sorted) => \case set-trichotomy-property xy \with {  | inr y<x => ((y :-: x :-: xs', consSorted (byRight y<x) xs-sorted), insertedHere idp idp)  | inl x<=y =>   \let ((result, result-sorted), result-spec) => insert (xs', tail-sorted x xs' xs-sorted) y   \in ((x :-: result, {?}), insertedThere idp result-spec) 
For a single fragment left without proof, Arend will output the following context value:
 Expected type: Sorted (x :-: (insert (\this, tail-sorted x \this \this) \this).1.1) Context:  result-sorted : Sorted (insert (\this, tail-sorted \this \this \this) \this).1.1  xs-sorted : Sorted (x :-: xs')  x : O  x<=y : Or (x = y) (O.< xy)  O : Dec  result : List O  y : O  xs' : List O  result-spec : InsertSpec xs' y (insert (xs', tail-sorted \this xs' \this) y).1.1 
To complete the proof, we will have to use the 
power of the 
\case operator 
to the full extent: we will use pattern matching with 5 different variables, and since the types of some variables may depend on the values of other variables, we will use dependent pattern matching.
The colon construction explicitly indicates how the type of some variables to be compared depends on the values of other variables (thus, in the type of variables 
xs-sorted, result-spec and 
result-sorted in each of 
\case instead of 
xs' and 
result will match the corresponding samples).
The 
\return construct associates the variables used to match the pattern with the type of expected result. In other words, for the current target, in each of the 
\case clauses, the corresponding sample will be substituted for the 
result variable. Without this construction, such a replacement would not be carried out, and the goal of all the 
\case clauses would coincide with the goal in place of the 
\case expression itself.
 \func insert {O : LinearOrder.Dec} (xs : SortedList O) (y : O) : \Sigma (ys : SortedList O) (InsertSpec xs.1 y ys.1) \elim xs  | (nil, _) => ((y :-: nil, singletonSorted), insertedHere idp idp)  | (:-: x xs', xs-sorted) => \case set-trichotomy-property xy \with {   | inr y<x => ((y :-: x :-: xs', consSorted (byRight y<x) xs-sorted), insertedHere idp idp)   | inl x<=y =>     \let ((result, result-sorted), result-spec) => insert (xs', tail-sorted x xs' xs-sorted) y     \in ((x :-: result,       \case result \as result, xs' \as xs', xs-sorted : Sorted (x :-: xs'), result-spec : InsertSpec xs' y result, result-sorted : Sorted result       \return Sorted (x :-: result) \with {        | nil, _, _, _, _ => singletonSorted        | :-: r rs, _, _, insertedHere y=r _, result-sorted => consSorted (transport (\lam z => (x = z) || (x < z)) y=r (Or-to-|| x<=y)) result-sorted        | :-: r rs, :-: x' _, consSorted x<=x' _, insertedThere x2=r _, result-sorted => consSorted (transport (\lam z => (x = z) || (x < z)) x2=r x<=x') result-sorted }), insertedThere idp result-spec) 
In the above block of code, the complicated first arguments to the 
consSorted constructor in the last two paragraphs of pattern matching deserve additional comment. To understand what both of these expressions mean, we replace them with the expression 
{?} And ask the Arend timer for determining targets at both positions.
You can see that both there and there the current target is the type 
(x = r) || O.< xr (x = r) || O.< xr . Moreover, in the context of the first goal, there are premises
 x<=y : Or (x = y) (O.< xy) y=r : y = r 
and in the context of the second - premises
 x<=x' : (x = x') || O.< xx' x2=r : x' = r. 
Intuitively clear: to prove the first goal, it is enough to substitute the variable 
r into the correct statement 
Or (x = y) (O.< xy) instead of the y variable, and then switch to the propositionally truncated type 
|| using the 
Or-to-|| function defined in Section 1.3 . To prove the second goal, just substitute in 
(x = x') || O.< x x' (x = x') || O.< x x' instead of the variable 
x' variable 
r .
To formalize the described expression substitution operation, a special 
transport function exists in the standard Arend library. Consider her signature:
 \func transport {A : \Type} (B : A -> \Type) {aa' : A} (p : a = a') (b : B a) : B a' 
In our case, instead of the variable 
A we need to substitute the type 
OE (it can be omitted explicitly if the other 
transport arguments are specified), and instead of 
B , the expression 
\lam (z : O) => (x = z) || (x < z) \lam (z : O) => (x = z) || (x < z) .
Implementation of the insertion sorting algorithm together with the specification does not cause any special difficulties: in order to sort the list 
x :-: xs' , we first sort the tail of the list 
xs' using a recursive call to 
insertSort , and then insert the element 
x inside this list with preserving the order for help access to the already implemented 
insert function.
 \func insertSort {O : LinearOrder.Dec} (xs : List O) : \Sigma (result : SortedList O) (Perm xs result.1) \elim xs | nil => ((nil, nilSorted), permTrivial idp) | :-: x xs' => \let | (ys, perm-xs'-ys) => insertSort xs'                      | (zs, zs-spec) => insert ys x                  \in (zs, permInsert perm-xs'-ys (insertedHere idp idp) zs-spec) 
We fulfilled the original goal and implemented sorting lists on Arend. The entire Arend code given in this section can be downloaded in one file 
from here .
One might ask how one would have to change the implementation of the 
insert function if instead of the strict 
LinearOrder.Dec orders we used the non-strict 
TotalOrder orders? As we recall, in the definition of the totality function, the use of the truncated operation 
|| was quite significant, that is, this definition is not equivalent to a definition in which instead of 
|| used by 
Or .
The answer to this question is as follows: it is still possible to build an 
insert analogue for 
TotalOrder , however, for this we would have to prove that the type of the 
insert function is a statement (this would allow us in the definition of 
insert to make a comparison with the sample according to the 
totality xy statement).
In other words, we would have to prove that there is only one ordered list, up to equality, which is the result of inserting the element 
y into the ordered list 
xs . It is easy to see that this is a true fact, but its formal proof is no longer so trivial. We leave verification of this fact as an exercise for the interested reader.
3. Concluding observations
In this introduction, we got acquainted with the main constructs of the Arend language, and also learned how to use the class mechanism. We managed to implement the simplest algorithm along with the proof of its specification. Thus, we have shown that Arend is quite suitable for solving "everyday" problems, such as, for example, program verification.
We have mentioned not all Arend features and features. For example, we said almost nothing about 
types with conditions that allow you to “glue” various type constructors with some special parameter values for these constructors. For example, an implementation of the integer type in Arend is given using types with conditions as follows:
 \data Int | pos Nat | neg Nat \with { zero => pos zero } 
This definition says that integers consist of two copies of the type of natural numbers, in which "positive" and "negative" zeros are identified. Such a definition is much more convenient than the definition from the standard Coq library, where the “negative copy” of natural numbers has to be “shifted by one” so that these copies do not intersect (it is much more convenient when 
neg 1 notation stands for -1, not -2) .
We did not say anything about the algorithm for deriving predicative and homotopy levels of classes and their instances. We also hardly mentioned the type of interval 
I , although it plays a key role in the theory of types with an interval, which are the logical basis of Arend. To understand how important this type is, it’s enough to mention that in Arend type equality is defined through the concept of an interval.
Comparison with the sample in a variable having the type of interval is carried out according to rather specific rules, which we also did not say anything about in this article (the so-called homotopy comparison with the sample).Posted by Sergey Sinchuk , Senior Researcher , HoTT and Dependent Types at JetBrains Research.