Instructor: Let's quickly demonstrate how concat works on an array. We'll use the data array concat, and we'll type out concat, and we'll have an array. Inside, we'll nest two other arrays. In the first one, we'll put 1, 2. In the second one, we'll put 3, 4. If we look at the output, that returns our values in a single array, which is 1, 2, 3, 4.
Next, our logs show myList lists. This is to demonstrate it's the equivalent of our nested array, but in a list format. Now, let's import a concat for our list. We'll comment out data.array, and we'll import it from data.list. Go back down to the bottom, and we'll do concat myList list. Like the array, it accumulates 1 and 2 and 3 and 4 into a single list, which 1, 2, 3, 4, and nil.
Let's create our own concat for lists. We'll call it concatLists, and that has a type of forall a list -- list of a, and it returns us a list of a. On the next line, we've got concatLists nil and that equals nil. On the line after, we've got concatLists X cons Xs, and that equals X append concat list, Xs.
Let's try this out. We'll copy this line, and we'll change concat to concatLists. Looking at our output, and they're both exactly the same, 1, 2, 3, 4, and nil. Let's take a little closer look at what happens when we put our list through concat list.
Our list isn't nil, that'll skip that case, and then on to the second case. We'll do X cons Xs. Let's see what X actually is. We could do that by removing this part, and then you'll see that X equals 1, 2, and nil. Now, let's see what Xs is. We'll need to change that up here to list of lists, because it's what it's returning us.
If we look at the output, it's 3, 4, nil, nil. It's still a nested list at the moment. Let's put things back, and then we're recursively calling our nested list of 3, 4, nil, nil. If we put that through, that'll give us 3, 4, nil. When that recursion is done, we'll be appending 1, 2, nil with 3, 4, nil.
Let's have a look what this looks like. We'll put it down here, and 1, 2, nil, 3, 4, nil gives us 1, 2, 3, 4, nil. There you have it. That's how we do our concat lists.
Next, let's have a little play with concatmap. We would change this line to say concatmap, function, we'll leave empty for now, and then, it'll be an array inside of an array. The first one will have 1 and 2, the second one 3 and 4.
Back to our function, and we'll put a map. We'll do _ +1, each element that comes into our map, we'll take that element and add one to it. If you look at the output, we've actually taken our nested array, added 1 to each element, and concatenated those elements into one array.
Let's try out the same thing with the list. We'll add concatmap to data.list. We'll copy myList of lists, and we'll add it to the end. Looking at our results, that will give us 2, 3, 4, 5, and nil. Right. Let's make our own concatmap for lists.
We'll call it concatMapLists, and that'll have a type of forall a b. That'll take a function of list to a, and give us back a list to b. This second argument would be a list of list a, and it'll return us a list of b. On the next line, we'll do a bit of pattern matching. It'd be concatMapLists F and nil. If the second argument is nil, we'll just return nil.
On the next line, we'll do concatMapLists F X cons Xs. That'll equal F X concatenated with concatMapLists F Xs. This is really similar to concat list, but what we're doing is we're passing around the function. In our case, we're mapping and we're adding 1 to the elements.
You can see in the line it says F X, F of X will be mapping over 1 and 2. That'll give us 2 and 3. Then, we'll recursively call concatMapLists, passing in the F again and the Xs. That would be 3 and 4. Then, we'll map +1 with those, so that'd be 4 and 5. If we append those together and concat the results, that'd be 2, 3, 4, 5, and then nil.
There you go. You've been able to create a concat and a concatmap for lists.