How can I get multiple nth elements in a list? - list

I want to know how I can get multiple elements in a list in one function
for example if I wanted to get elements 1 2 3 and 4 from list a, I would have to type a!!0 ++ a!!1 ++ a!!2 ++ a!!3. This takes up a lot of space especially if the list name is more than one character. so I'm wondering if I can do something like a!![0,1,2,3] instead and get all of those elements in a much shorter way. Thank you.

You can work with a mapping where you lookup all items for a list, so:
map (a !!) [0,1,2,3]
If you are however interested in the first four items, you can work with take :: Int -> [a] -> [a]:
take 4 a
especially since looking up by an index (with (!!)) is not a common operation in Haskell: this is unsafe since it is not guaranteed that the index is in bounds. Most list processing is done with functions like take, drop, sum, foldr, etc.

Related

Implementing own Union function without going through lists twice

I have to write a Union function using recursion
The ouput has to be the Union (no duplicates) of two lists. My teacher said the implementation has to be recursive and we cannot go through the lists twice but I don't think I can come up with a way of solving the problem without going through the lists twice?
My ideas which would solve the problem (but involve going through lists twice):
- Merge then remove duplicates
- Sorting the lists, then merge
Any hints or help would be appreciated
Edit: Well so I got to combine both lists by doing this:
union1 :: (Eq a) => [a] -> [a] -> [a]
union1 xs [] = xs
union1 [] ys = ys
union1 (x:xs)(y:ys) = x:y:union1(xs)(ys)
Then I thought I could use nub or a similar function to remove the duplicates but I got stuck thinking because then I would be going through the lists twice, right?
What is list union?
I would like to first point out that the requirements your teacher gave you are a bit vague. Moreover, union on multisets (aka sets that can have duplicates, like lists) have two different definitions in mathematics (other source). I am no mathematician, but here is what I was able to glean from various internets. Here is one definition:
λ> [1,2,2,3,3,3] `unionA` [1,2,2,2,3] --also called multiset sum
[1,1,2,2,2,2,2,3,3,3,3]
This is simply (++), if you're not worried about ordering. And here is the other:
λ> [1,2,2,3,3,3] `unionB` [1,2,2,2,3]
[1,2,2,2,3,3,3] --picks out the max number of occurrences from each list
Adding to this confusion, Data.List implements a somewhat quirky third type of union, that treats its left input differently from its right input. Here is approximately the documentation found in comments the source code of union from Data.List:
The union function returns the list union of the two lists. Duplicates, and elements of the first list, are removed from the the second list, but if the first list contains duplicates, so will the result. For example,
λ> "dog" `union` "cow"
"dogcw"
Here, you have 3 possible meanings of "union of lists" to choose from. So unless you had example input and output, I don't know which one your teacher wants, but since the goal is probably for you to learn about recursion, read on...
Removing duplicates
Removing duplicates from unordered lists in Haskell can be done in linear time, but solutions involve either random-access data structures, like Arrays, or something called "productive stable unordered discriminators", like in the discrimination package. I don't think that's what your teacher is looking for, since the first is also common in imperative programming, and the second is too complex for a beginner Haskell course. What your teacher probably meant is that you should traverse each list explicitly only once.
So now for the actual code. Here I will show you how to implement union #3, starting from what you wrote, and still traverse the lists (explicitly) only once. You already have the basic recursion scheme, but you don't need to recurse on both lists, since we opted for option #3, and therefore return the first list unchanged.
Actual code
You'll see in the code below that the first list is used as an "accumulator": while recursing on the second list, we check each element for a duplicate in the first list, and if there isn't a duplicate, we append it to the first list.
union [] r = r
union l [] = l
unionR ls (r:rs)
| r `elem` ls = unionR ls rs --discard head of second list if already seen
--`elem` traverses its second argument,
--but see discussion above.
| otherwise = unionR (r:ls) rs --append head of second list
As a side note, you can make this a bit more readable by using a fold:
union xs = foldl step xs where --xs is our first list; no recursion on it,
--we use it right away as the accumulator.
step els x
| x `elem` els = els
| otherwise = x : els

Correct way to add an element to the end of a list?

I was reading on this Haskell page about adding an element to the end of a List.
Using the example, I tried it out for my self. Given the following List I wanted to add the number 56 at the end of it.
Example:
let numbers = [4,8,15,16,23,42]
numbers ++ [56]
I was thrown off by this comment:
Adding an item to the end of a list is a fine exercise, but usually
you shouldn't do it in real Haskell programs. It's expensive, and
indicates you are building your list in the wrong order. There is
usually a better approach.
Researching, I realize that what I'm actually doing is creating a List with 56 as the only element and I'm combining it with the numbers list. Is that correct?
Is using ++ the correct way to add an element to the end of a List?
++ [x] is the correct way to add an element to the end of a list, but what the comment is saying is that you shouldn't add elements to the end of a list.
Due to the way lists are defined, adding an element at the end always requires making a copy of the list. That is,
xs ++ ys
needs to copy all of xs but can reuse ys unchanged.
If xs is just one element (i.e. we're adding to the beginning of a list), that's no problem: Copying one element takes practically no time at all.
But if xs is longer, we need to spend more time in ++.
And if we're doing this repeatedly (i.e. we're building up a big list by continually adding elements to the end), then we need to spend a lot of time making redundant copies. (Building an n-element list in this way is an O(n2) operation.)
If you need to do this, there is usually a better way to structure your algorithm. For example, you can build your list in reverse order (adding elements at the beginning) and only call reverse at the end.
It's the correct way in that all ways of doing it must reduce to at least that much work. The problem is wanting to append to the end of a list at all. That's not an operation that's possible to do efficiently with immutable linked lists.
The better approach is figuring out how to solve your specific problem without doing that. There are a lot of potential approaches. Picking the right one depends on the details of what you're doing. Maybe you can get away with just using laziness correctly. Maybe you are best off generating the list backwards and then reversing it once at the end. Maybe you're best off using a different data structure. It all depends on your specific use case.

How to make predicate repeat N number of times in Prolog?

I have a number of lists containing letters and I have written a predicate that checks whether or not there are duplicates present in one of these given lists:
noDuplicates([]).
noDuplicates([H|T]):-
not(member(H, T)),
noDuplicates(T).
I have 10 lists and I want to know if there are no duplicates in any of them, so I made them into sublists of one big list, something like:
[[A,B,C], [C,A,D], [E,F,G]...]]
(So there can be duplicates in the big list, but not the individual sublists).
I get that I have to do the duplicates test 10 times; once for every sublist, but how do I write this in Prolog? I could probably write it down 10 times, but my guess is I can use recursion to make prolog repeat itself until all sublists have been checked.
So basically: I want this predicate to repeat itself N times, until N is 10. I'm really struggling with it though. Does anyone have any idea on what to do?
Let us generalize the question as follows:
You have a predicate p/1 that expresses what you want for a single list.
Thus, to lift this definition to a list of such lists, you can define a predicates ps/1 as follows:
ps([]).
ps([L|Ls]) :-
p(L),
ps(Ls).
Every time you see this pattern, you can use maplist/2. That is, the above is equivalent to:
ps(Ls) :- maplist(p, Ls).
The goal maplist(p, Ls) is true iff p holds for each element L of Ls.
Note that it will limit your understanding of Prolog if you think in terms of "looping" and "repeating". These are imperative notions and only make sense when the list is already fully instantiated. However, from Prolog, we expect more than that: We expect a full-fledged relation to also generate lists for which the relation holds. And in such cases, there is nothing to "repeat" yet: We start from nothing, and ask Prolog what solutions there are in general.
Thus, think in terms of describing when the relation ps/1 holds for lists of lists:
It holds for the empty list [].
It holds for the list [L|Ls] if our initial predicate (p/1) holds for L, and ps/1 holds for the remaining list Ls.
This declarative reading is applicable in all directions, no matter how many list elements are already instantiated, if any. It works for 10 lists just as well as for zero and 50.

How can I build a list recursively? ML

I have to write a recursive function that takes a list of three elements, and returns another list created using those three elements. For example I might have a list like [a,b,c], and a function needs to multiple a by b c times. So [2,3,5] would create a list like [2,6,18,54,162,486]
I understand the hd, tl, #, and :: list operators, but I don't understand the logic of building the list.
If I multiply hd([2,3,5])* hd(tl([2,3,5)) I'll get six. But where do I attach that? I would need new logic on every call to go deeper in the list multiplying the last element by 3.
The point is, your recursive function should return the list, and the call which satisfies the stopping requirement should return empty list (or some starting list).
In this case, the function appends (a * b) to the start of list of the next values. The decreasing c provides a counter, while intermediate result (a * b) serves as a base for calculations further down the line. So here the list grows backwards, from the greatest values at the tail to the smallest at the head.

Why are arbitrary sized tuples useful? (Template Haskell)

In the introductory text for Template Haskell one of the examples for why Template Haskell is useful is working with arbitrary sized tuples.
What is the purpose of arbitrary sized tuples? If the data type is the same why not use a list? And if the data types in the tuple are different, how can it be expanded to arbitrary sizes?
With arbitrary one means arbitrary at compile time. So if you want tuples with fifteen elements, template Haskell will generate a function for a tuple with fifteen elements. After compilation however, the number of elements is fixed. The advantage of using a tuple is that you can access each element in constant time O(1). So you can use the type system to enforce the tuple still contains a fixed amount of elements.
Furthermore the sel in the example can work with tuples where the elements have arbitrary types. For instance sel 2 3 will generate a function:
$(sel 2 3) :: (a,b,c) -> b
$(sel 5 5) :: (a,b,c,d,e) -> e
whereas if you use a list [a], this means that the list can only contain data for a certain type:
(!!3) :: [a] -> a
so all items have type a. Furthermore in this case you are not sure that the list will have three elements. The more you can check at compile time, the more safe your code is (and in many cases more efficient as well).
A list on the other hand has an arbitrary size at runtime. The same type - for instance [Int] - can specify a list with two, five, hundred or thousands of integers. Furthermore in the case of a list, accessing the k-th element requires O(k) time. There are datastructures like arrays that of course can access elements in constant time.