how does xs in this function work? - haskell

I am reading Hutton's book, Programming in Haskell.
Here is a function:
pairs :: [a] -> [(a,a)]
pairs xs = zip xs (tail xs)
e.g.
>pairs [1,2,3,4]
>[(1,2),(2,3),(3,4)] --result
Problem is how to read this function ? from left to right?
I am confused how "tail" leave 1 element and then combine it with next element using "zip"
Since "tail" suppose to get all remaining elements from the list right?

I haven't read the book you mentioned, but I'll try to explain what I know.
You're right about the tail function returning everything except the first element of the list. Let's see how zip works,
zip [1, 2, 3, 4] [5, 6, 7, 8]
gives,
[(1, 5), (2, 6), (3, 7), (4, 8)]
Now, consider the output we need from the input we have, observe the transformation required from input to output,
[1, 2, 3, 4] -> [(1,2),(2,3),(3,4)]
From the above application of zip, we can see the output we need can be obtained by calling zip with,
zip [1, 2, 3] [2, 3, 4]
Now, from the docs on zip function, we can see that if the two given lists are of unequal length, the extra items in the longer list are discarded. So, we'd get the same result with,
zip [1, 2, 3, 4] [2, 3, 4]
in which the last 4 in the first input list would be discarded and we get the result we want.
This can be written in a function as,
pairs xs = zip xs (tail xs)
If it is something else you are confused about, do let me know.

zip takes 2 arguments. tail returns its argument with the first element removed, but does not modify its argument.Therefore [1, 2, 3, 4] gets zipped with [2, 3, 4].

Related

Are there any difference between Y and *Y, where Y is a list used as input argument?

I was using the torch.tensor.repeat()
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
period = x.size(1)
repeats = [1,2]
result = x.repeat(*repeats)
the result is
tensor([[1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6]])
if I get result as follows
result = x.repeat(repeats)
the result is the same
tensor([[1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6]])
It seems that x.repeat(repeats) and x.repeat(*repeats) work the same.
Does it mean that, for an input parameter, e.g, Y, I can use either Y or *Y
Kinda. If repeats is a (list or tuple) of ints, then it is equivalent. But in general the rule appears to be:
If the first argument is a list or tuple, take that as repeats. Ignore all other arguments.
Otherwise, take the full *args as repeats
So if your repeats is something weird like repeats=((1,2),(3,4)), then a.repeat(*repeats) succeeds and is the same as a.repeat(1, 2)==a.repeat((1, 2)) and a.repeat(repeats) fails.
Note: This is observational based on my own tests. The only official documentation is the defined type of the function, e.g. repeat(torch.Size or int...) which isn't perfectly clear with regards to semantics.
You can also get error messages like this:
TypeError: repeat(): argument 'repeats' (position 1) must be tuple of ints, not tuple
when you pass floats. In general error reporting could be better.

how to append a list of lists in Groovy

How do I append a list of lists in a purely functional way in groovy? Like if I have a list in variable "a", with a method "b" that returns a list, I can do this:
a.*b
=> [[1, 2], [3, 4, 5], [6]]
but what I really want is:
[1, 2, 3, 4, 5, 6]
This would be easy for example in the Scheme programming language:
(define foo '((1 2) (3 4 5) (6)))
(apply append foo)
=> (1 2 3 4 5 6)
how to do (apply append list-of-lists) in groovy? I know I can do flatten() but that goes arbitrarily deep, and that's not what I want.
Your example code shows the spread-operator. So instead of using that,
you can use collectMany.
If you prefer to build the intermediate result and then "apply" one
function to merge all lists, you can use sum, which on an array
concats all elements.
def a = [[b:[1]],[b:[2,[3]]]]
println(a.collectMany{ it.b })
// → [1, 2, [3]]
println(a*.b.sum())
// → [1, 2, [3]]

How to get particular element from list of tuples

I have this list of tuples:
l1 = [(1, 8), (6, 8), (8, 7), (2, 6)]
I want to compare 1st element of each tuple with 1st element of next tuple
How can I access the next tuple's 1st element?
Since operating lists is a bit easier than tuples, I first made this as list of list as follows:
l1 = [[1, 8], [6, 8], [8, 7], [2, 6]]
and then tried this:
for i in l1:
if l1[i][1] == l1[i+1][1]:
...
but l1[i+1][1] doesn't work
what am I doing wrong in (i+1) code
Try to use range with the length of your list -1 :
for i in range(len(l1) - 1) :
if l1[i][0] == l1[i+1][0]:
...
with this you won't get indexError when reaching your last member of the list.
While comparing adjacent elements when traversing through the elements always make sure your stopping condition is the second last element.
Also if you are comparing the first element your indexing should start at 0 and not 1.
for i in range(len(l1)-1):
if l1[i][0] == l1[i+1][0]:

Merge multiple lists

Is there a way, in haskell to merge multiple lists to one list?
e.g.:
Input:
[
[0,2,0,4,0,6,0,1,0,3,0,0,0,0,0],
[0,0,3,0,0,6,0,0,2,0,0,0,0,0,1],
[0,0,0,4,0,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,3,0,0,0,0,1]
]
Expected Output:
[0,2,3,4,0,6,0,1,2,3,0,0,0,0,1]
You can use transpose (you may need Data.List) to swap lines and columns of your table to simplify the processing.
Example:
[[0, 1, 0, 2, 3],
[0, 0, 2, 0, 3]]
becomes
[[0, 0],
[1, 0],
[0, 2],
[2, 0],
[3, 3]]
Now you have a list of old columns, so you can process them one by one. For example, you could write such a function:
merge list = case dropWhile (== 0) of [] -> 0
(x:_) -> x
Here we drop all leading zeros from the list, and look if the remaining list has some value, then we take it, otherwise we get 0 as a result.
Now we can use this function to process the transposed table like this:
mergeLists lists = map merge (transpose lists)
Now, we can get rid of parentheses:
mergeLists lists = map merge $ transpose lists
Or even get rid of argument (use composition):
mergeLists = map merge . transpose
Here we say, that merging lists is 1) transposing the table and 2) processing each column with merge. Each of these three versions is equivalent, so you can use any of them.
Some further reading on composition: http://learnyouahaskell.com/higher-order-functions#composition
You can see how it works here: https://repl.it/repls/ReasonablePerfectOptimization
EDIT: fixed merge to use pattern matching

Unflattening list returns unexpected Error in Python

I have read all the posts about unflattening lists on Stackoverflow but I can't find a solution to my problem.
I have two lists and I want to add one element from list2 to every element in list1.
l1 = [[1,2],[3,4]]
l2 = [5, 7]
and the result I am after is
[[1, 2, 5], [3, 4, 6]]
I have tried this code
for i in range(len(l2)):
l1[i].extend(l2[i])
print(l1)
but returns an Error "TypeError: 'int' object is not iterable"
When every element of l2 is a list by itself e.g. l2 = [[5],[7]]
my code works fine. Why is that? And how do I adjust my code to work when l2 is in this format l2 = [5, 7]
Use zip() to iterate over two or more things in parallel. Using range() to make indexes when you don't need them is unpythonic.
xss = [[1,2],[3,4]]
ys = [5,7]
for xs, y in zip(xss, ys):
xs.append(y)
print(xss)
[[1, 2, 5], [3, 4, 7]]
list1.extend(list2) is to create list1+list2. But you are not providing list2, instead, it is just an element. The right function to do that is list1.append(element2), which is same as list1+[element2]
l1 = [[1,2],[3,4]]
l2 = [5, 7]
for i in range(len(l2)):
l1[i].append(l2[i]);
print(l1)
[[1, 2, 5], [3, 4, 7]]
Extend is for objects.
Append is what you need here.

Resources