In this session, we learn about more methods on the list type and we'll also introduce a new data type the topper. We look at these things in the context of a somewhat larger example, namely we want to design a function to sort lists that's more efficient than insertion sort. A good algorithm for this is merge sort. The idea is as follows, if the list consists of zero or 1 element, it's already sorted. Otherwise we separate the list into two sub lists. Each surplus should contain about half the elements of the original list. Then we sought the two sub lists each in turn, and finally we merged the two sorted sub lists into a single sorted list. He is an outline of the implementation of that algorithm in Skara. We define a function m sort short for merge sort. That takes a list of instant returns, a list of its. We compute the Length of the list divided by two. If that is zero. The original list was of length zero or 1, then we return the original list. Otherwise we postulate emerge function for two sorted lists. So it remains to the triple question marks here remain to be filled in. We split the list at the point in the middle. That gives us two sub lists 1st and 2nd. We recursive lee sort, 1st and 2nd using merge sort and we merge the results of those two recursive sorts. That sorting function used the split at function on lists that returns to sub lists the elements up to the given index and the elements from that index. And those lists are returned in a pair. A pair consisting of the 2/2 X&Y. Is written X comma Y in parenthesis. In Skara for instance, here you can say well pair Equals answer 42 and that would give you a pair of type string into and value answer 40 two. So the type of the pair is string into its again, the individual types in parentheses separated by commas, pears can also be used in patterns. So you can decompose that pair by writing well label value equals pair and that would give you two values. A label Which is the answer, a string and a value which is an integer 42. The whole thing works analogous lee for topples with more than two elements. So you can have as many parts in a pair as you want. So using pairs, we can write the extension methods split at like you see here. So it's it's defined on lists of tea for arbitrary T. It takes on it and it gives you back a pair where the first element of the pair is excess take. And so the elements of the list up to index end and the second half is excess drop. And so all elements of the list except in first ones. Now we can test that by writing let's say split at two with our list of excess from the last section. And that would give us a list where the original list ABCD was split into two halves, AB and CD. So so far every type in scala was an instance of some class. The same holds for couples. So for smallish and the topple type T. One to T. M is just an abbreviation for the parameter. Rised types scalar topple then the number end and then the arguments T. One to T. N. So the pair and strength would be an abbreviation of apple too. I leave out the scholar prefix of end strength. Yeah. For larger to apples to apples length with Length more than 22. We have a special class topple XXL that essentially collects all elements in an array and then stores them in the top six hour class. So yes topples are instances of classes but there is a difference whether the trouble is of moderate size up to 22 or beyond that. Where we have essentially a class that collects topples of all different sizes. So if we look at each of the top of classes then they're all modeled after the following pattern. Here we have the example with top couple to pair class. So it takes to type parameters T. One and T. Two. And it takes two selectors which are written _ one and _ too. And the first one is of type T one. The second is of type T two. They're both co variant. So topples arco variant in both of their argument types. And they overwrite it to string methods so that they look like appel because tables are case classes, it means that these selector values are also available as fields. So instead of the pattern binding, well labeled value equals pair, you could also have written well label equals pair dot underscore one, which selects the first half of the pair and val value equals pair underscore two. Normally at least if you want to match on all elements of a topple, the para matching form is more concise and it's clearer so it's generally preferred. The individual selectors can sometimes be useful if you have a long couple and you just want to select a single element for instance. So to complete merge sort, we still have to define the merge function here. It is. So merge takes two lists of integers which are both assumed to be already sorted. It then does a pattern match on the pair of excess and wires. So we form a pair of the two lists and we match with pears in turn, so if the two lists are nil Y. Yes, that means the first list is nil, the second list is arbitrary, then we return the second list. There's nothing to merge. If the second list is nil and the first list is either now or has some elements, we return the first list if both lists are non empty. So the first list, let's say starts with X. And the second list with the variable Y. Then we have a distinction whether X or Y is the smaller elements. So if X is less than why, then the merged list would start with X. And be followed by the merger of the rest of the excess list and all of the buyers list. Otherwise it would start with Y. And be followed by the merge of all of the access list and the rest of the wires list. Okay. So that was merge sort on interests. But of course we'd like to generalize it so that it can also be used for list with elements other than it if we just add a type parameter to and sort like this. So we replaced the hint by T what he's a type parameter. That wouldn't work. Why? Well, because the comparison emerges not defined for arbitrary types team. So let's look at merger again. Here's the comparison. It is defined forint of course. But it wouldn't be defined for arbitrary types. T for if it's just given a type T of which we know nothing that we cannot assume that it has a comparison function less than defined on it. But what we can do is we can parameter rise, merge with the necessary comparison function. So let's do that. Next. So here we have a new version of merge sort, which is now polymorphic. It takes lists of tea for arbitrary T and it also takes a comparison function less than that. Takes two elements of type T and returns a bully. So if we have set up things like this than in the recursive call, we have to go on and pass less than two. The two recursive invocations of mercy because otherwise they would miss a parameter and then merge also needs to be adapted. The merge function is defined inside merch. So so it would see the less than function. That's okay. But here at the comparison we would have to call that comparison function less than X and Y. Instead of calling X less than y. What we did previously we can now call sort as follows to sort a list of interfaces. We pass that list excess and the comparison function less than on Integris to sort a list of fruits, which is a list of string. We past the comparison function on string, which in this case would be the function that takes two strings applies to compare to function which is a function known in java from strengths and says the value of compared to should be less than zero. So that's equivalent to a less than on strength. Not that the type arguments of them sort have been inferred in each case, so we could have written in here and string here, but that's not necessary because the compiler will infer it from the types of the arguments and as another simplification. The compiler can also in for the types of the parameters here, because it knows by when it sees the list exists, that we intend to do a merge sort on int so we need a comparison function on two inches. So that means we can write it even shorter, merge sort excess and X comma y, arrow X less than Y. So we don't really need the parameter types here, nor do we need them in the string example you could say well, even that is too much noise for me. Couldn't the compiler have inferred the correct comparison function for the the parameter type. So that means it can be now asked the compiler not just to infer a type but to infer a value that we say, well, four and what's the correct comparison function or four strings? What's the correct comparison function? And in fact, we will see that this is possible, but it will take us several weeks to get there. We will have a week on implicit parameters that does precisely that can infer missing parameters from their types.