I've been playing around with some Haskell functions in GHCi.
I'm getting some really funny behaviour and I'm wondering why it's happening.
I realized that the function min is only supposed to be used with two values. However, when I use three values, in my case
min 1 2 -5
I'm getting
-4
as my result.
Why is that?
You are getting that result because this expression:
min 1 2 -5
parses as if it were parenthesized like this:
(min 1 2) -5
which is the same as this:
1 -5
which is the same as this:
1 - 5
which is of course -4.
In Haskell, function application is the most tightly-binding operation, but it is not greedy. In fact, even a seemingly simple expression like min 1 2 actually results in two separate function calls: the function min is first called with a single value, 1; the return value of that function is a new, anonymous function, which will return the smaller value between 1 and its single argument. That anonymous function is then called with an argument of 2, and of course returns 1. So a more accurate fully-parenthesized version of your code is this:
((min 1) 2) - 5
But I'm not going to break everything down that far; for most purposes, the fact that what looks like a function call with multiple arguments actually turns into a series of multiple single-argument function calls is a hand-wavable implementation detail. It's important to know that if you pass too few arguments to a function, you get back a function that you can call with the rest of the arguments, but most of the time you can ignore the fact that such calls are what's happening under the covers even when you pass the right number of arguments to start with.
So to find the minimum of three values, you need to chain together two calls to min (really four calls per the logic above, but again, hand-waving that):
min (min 1 2) (-5)
The parentheses around -5 are required to ensure that the - is interpreted as prefix negation instead of infix subtraction; without them, you have the same problem as your original code, only this time you would be asking Haskell to subtract a number from a function and would get a type error.
More generally, you could let Haskell do the chaining for you by applying a fold to a list, which can then contain as many numbers as you like:
foldl1 min [1, 2, -5]
(Note that in the literal list syntax, the comma and square bracket delimit the -5, making it clearly not a subtraction operation, so you don't need the parentheses here.)
The call foldl1 fun list means "take the first two items of list and call fun on them. Then take the result of that call and the next item of list, and call fun on those two values. Then take the result of that call and the next item of the list..." And so on, continuing until there's no more list, at which point the value of the last call to fun is returned to the original caller.
For the specific case of min, there is a folded version already defined for you: minimum. So you could also write the above this way:
minimum [1, 2, -5]
That behaves exactly like my foldl1 solution; in particular, both will throw an error if handed an empty list, while if handed a single-element list, they will return that element unchanged without ever calling min.
Thanks to JohnL for reminding me of the existence of minimum.
When you type min 1 2 -5, Haskell doesn't group it as min 1 2 (-5), as you seem to think. It instead interprets it as (min 1 2) - 5, that is, it does subtraction rather than negation. The minimum of 1 and 2 is 1, obviously, and subtracting 5 from that will (perfectly correctly) give you -4.
Generally, in Haskell, you should surround negative numbers with parentheses so that this kind of stuff doesn't happen unexpectedly.
Nothing to add to the previous answers. But you are probably looking for this function.
import Data.List
minimum [1, 2, -4]
Related
I ran into this statement while I was coding:
l = [1,2,3]
print(l[0:-1:-1])
I was expecting this piece of code gives me [1] however it gives me [], makes me think I must have mis-understood python slice operation, can someone explain what is going on here?
In a slice,
The first integer is the index where the slice starts.
The second integer is the index where the slice ends.
The third integer specifies a stride or step causing the resulting slice to skip items. -1 for reverse the output.
l[0:-1:-1]
is equivalent to
l[len(l)-1:len(l)-1:-1]
The first index converted 0 to len(l)-1, because you added -1 in the last index to reverse the list. This will always give you an empty list.
When you use slice in python and you type
l[x:y:-1]
it would somehow be equivalent to
l.reverse()
print(l[y:x])
l.reverse()
but with the difference that -1 reverses the list elements with their indexes
so if you type
l=[1, 2, 3]
l[2:0:-1]
the output will be
[3, 2]
The reason for empty list is that you change the order of indexes so it wont find any element in that window...
I gathered some information after talking with friends about this problem, now we kind of believe this is what happened: when I do l[0:-1:-1], the first thing interpreter will do is to convert that second -1 to the positive index, which is 2 in my case. Then it will iterate backward with the terminating condition being "start <= end", in this case since at the very beginning it will find 0 <= 2, so it will directly terminate, results in the output array being empty.
I didn't really get what the two other answers are saying here (silly me), maybe they are right, I need to look into the python source code for a 100% certain explanation, but for now I believe what I just stated here is the case.
I am trying to take a starting and a length and return a list of lists that gradually increases an even starting integer by 2
For example:
evenIncrease 6 3
Should return:
[[6],[6,8],[6,8,10]]
I am new to Haskell and so far my attempt looks like this:
evenIncrease n l = [[n..i] | i <- [n..n+(l*2)-2], even i]
but when I attempt my example of evenIncrease 6 3, I get:
[[6],[6,7,8],[6,7,8,9,10]]
which is almost what I'm looking for but I don't understand why there are still odd numbers in the inner lists when I am using the guard "even i"
any ideas?
You're correctly generating only even endpoints, but [n..i] still increments by 1, so even though both endpoints are even, you still get e.g [6..8] = [6,7,8]. Try [n,n+2..i].
I'm learning the fundamentals of Python right now by reading Thinking Python.
As I was reading a chapter about "fruitful" function, that is, a function that "returns" a value, I came across this problem. I can more or less figure out how the code of the factorial function works, but not exactly. I have trouble in understanding precisely the flow of a function involving self-calling or recursion. Btw, the printer statments in the code shown as below are scaffolding, a device used to track the flow of the function.
Without further ado, here is the code.
def factorial(n):
space=' '*(2*n)
print(space, 'factorial', n)
if n==0:
print(space, 'returning 1')
return 1
else:
recurse = factorial(n-1)
result=n*recurse
print(space, 'Returning', result)
return result
factorial(3)
The result or the output of this code is shockingly a v-shape. I, for the life of me, cannot figure out why the computer (or the compiler?) runs the program the way it does here. It seems like it firstly prints the first line and the last line, and then goes on to print the second line and the second to the last line...This is strange. You would expect that it always goes top down.
To illustrate the oddity of this issue, I hereby attach another piece of code that prints numbers as you count down. The code is similar and simpler, and you would expect it to behave similarly to the factorial function before. But it doesn't. There is no oddity in the order in which the lines of outcome are displayed or printed off.
def f(n):
print(n)
if n==0:
return 0
else:
print(3*n)
f(n-1)
return
I would really appreciate it if you could help me with this!
What might confuse you is that the recursive call does not happen at the end of the function as it is the case with your example f(). Which means, you have code that is executed before stepping into the recursion and code that is executed after stepping out of the recursion. Let's have a look at what happens in factorial:
The recursive step
Pick any recursion step i you like, which is not a base case. And then look at what the function does, without following through with the recursion.
For your factorial function, let's take the call factorial(i), where iis different from 0. That call does three things:
print 2*i spaces and "factorial i"
call factorial(i-1)
print 2*i spaces and "returning i"
So, the output is going to be:
(2*i spaces) factorial i
# everything factorial(i-1) outputs
(2*i spaces) returning i
You'll see that the output of factorial(i-1) gets sandwiched between the outputs of factorial(i). To perform the recursion, all you need to do is blow the pattern up. Let's take another step i-1 into account:
(2*i spaces) factorial i
(2*(i-1) spaces) factorial i-1
# everything factorial(i-1) outputs
(2*(i-1) spaces) returning i-1
(2*i spaces) returning i
So, you see that the indentation decreases with the calls since i decreases, which accounts for the v-shape.
The base case
It just prints
factorial 0
returning 1
Putting it all together
Now, you can find a verbal expression for what factorial(i) does:
factorial(i) produces the v-shape output
factorial i
factorial i-1
...
factorial 0
returning 1
...
returning i-1
returning i
With it being true for the case i == 0, conclude from there that is is true for i+1 if you assume that is is correct for i using the list in the section recursive step. Done that, you can be sure that is how factorial(n) works for any n >= 0.
Here's your code a bit restructured to make it easier to see:
def factorial(n):
space = ' '*(2*n)
print(space, 'factorial', n)
result = 1 if n == 0 else n*factorial(n-1)
print(space, 'Returning', result)
return result
And that's the output for factorial(3) with the "V shape" you mentioned:
factorial 3
factorial 2
factorial 1
factorial 0
Returning 1
Returning 1
Returning 2
Returning 6
It looks correct and does the job of calculating the factorial. To understand the order of prints seen here, think of the following:
The prints start with the call for 3, since that's your entry point
The indentation is then 3x2 = 6 spaces
Since for the calculation of factorial(3) the reuslt of factioral(2) is needed, this call comes next, with an indentation of 2x2 = 4 spaces. And so on for all further factorials. That's where the V shape of the first half of prints comes from.
All of these function calls are now "waiting" for a result to return, at the position of the recursive call in the code. Since only factorial(0) can deliver that return value without another recursion, it will print the first return value. With an indentation of 0.
With the above return value, the function call to factorial(1) can now calculate its result by multiplying the returned 1 with its own n, which gives 1. That's the next print, with an indentation of 2.
And so on for all the higher recursion steps, from the inside to the outside. And that's how the second half of the V shape is formed.
The vital thing to understand is that the result values of the functions (and thereby the print) can only occur at the END of the complete recursion tree that comes below it. That's why the call print factorial 3 is in the first line, while its corresponding Returning 6 print is at the last line - after the whole inner tree is finished.
Hard to say if I picked up the crunchpoint you had trouble understanding with, but I hope this somehow helps.
EDIT: infinite recursion
As an answer to your question, here's an example that shows how each recursive function call will have its own variable scope and therefore not know about the variables set in an another instance of the same function, ending up in a RecursionError when the maxiumum recursion depth of the call stack is reached.
def foo():
try:
print("a = ", a)
return # break out of loop
except UnboundLocalError:
print("no variable a. defining one now.")
a = 3
foo() # try again
foo()
k = reduce((lambda x,y,z : abs(x-y) + abs(y-z) + abs(z-x)) , range(List[0]))
is giving runtime error.
error message:- 'TypeError: () missing 1 required positional argument:
z'.
What could be the solution for it?
Your problem is (most likely, it is a little hard to judge without the rest of the code...) that you're using reduce (which takes a function with two arguments as its first argument) and pass it a function which requires three arguments. reduce then calls your anonymous function with two arguments which results in the exception.
As a side comment: I suggest avoiding the use of capitalized names (such as "List") for your variables. To most python programmers a capitalized name implies that a class.
From help(reduce)
reduce(...)
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
Seems like reduce passes only 2 parameters at a time and reduces them.
I'm a new student and I'm studying in Computer Sciences. We're tackling Haskell, and while I understand the idea of Haskell, I just can't seem to figure out how exactly the piece of code we're supposed to look at works:
module U1 where
double x = x + x
doubles (d:ds) = (double d):(doubles ds)
ds = doubles [1..]
I admit, it seems rather simple for someone that knows whats happening, but I can't wrap my head around it. If I write "take 5 ds", it obviously gives back [2,4,6,8,10]. What I dont get, is why.
Here's my train of thought : I call ds, which then looks for doubles. because I also submit the value [1..], doubles (d:ds) should mean that d = 1 and ds = [2..], correct? I then double the d, which returns 2 and puts it at the start of a list (array?). Then it calls upon itself, transferring ds = [2..] to d = 2 and ds = [3..], which then doubles d again and again calls upon itself and so on and so forth until it can return 5 values, [2,4,6,8,10].
So first of all, is my understanding right? Do I have any grave mistakes in my string of thought?
Second of all, since it seems to save all doubled d into a list to call for later, whats the name of that list? Where did I exactly define it?
Thanks in advance, hope you can help out a student to understand this x)
I think you are right about the recursion/loop part about how doubles goes through each element of the infinite list.
Now regarding
it seems to save all doubled d into a list to call for later, whats
the name of that list? Where did I exactly define it?
This relates to a feature that's called Lazy Evaluation in Haskell. The list isn't precomputed and stored any where. Instead, you can imagine that a list is a function object in C++ that can generate elements when needed. (The normal language you may see is that expressions are evaluated on demand). So when you do
take 5 [1..]
[1..] can be viewed as a function object that generates numbers when used with head, take etc. So,
take 5 [1..] == (1 : take 4 [2..])
Here [2..] is also a "function object" that gives you numbers. Similarly, you can have
take 5 [1..] == (1 : 2 : take 3 [3..]) == ... (1 : 2 : 3 : 4 : 5 : take 0 [6..])
Now, we don't need to care about [6..], because take 0 xs for any xs is []. Therefore, we can have
take 5 [1..] == (1 : 2 : 3 : 4 : 5 : [])
without needing to store any of the "infinite" lists like [2..]. They may be viewed as function objects/generators if you want to get an idea of how Lazy computation can actually happen.
Your train of thought looks correct. The only minor inaccuracy in it lies in describing the computation using expressions such has "it doubles 2 and then calls itself ...". In pure functional programming languages, such as Haskell, there actually is no fixed evaluation order. Specifically, in
double 1 : double [2..]
it is left unspecified whether doubling 1 happens before of after doubling the rest of the list. Theoretical results guarantee that order is indeed immaterial, in that -- roughly -- even if you evaluate your expression in a different order you will get the same result. I would recommend that you see this property at work using the Lambda Bubble Pop website: there you can pop bubbles in a different order to simulate any evaluation order. No matter what you do, you will get the same result.
Note that, because evaluation order does not matter, the Haskell compiler is free to choose any evaluation order it deems to be the most appropriate for your code. For instance, let ds be defined as in the final line in your code, and consider
take 5 (drop 5 ds)
this results in [12,14,16,18,20]. Note that the compiler has no need to double the first 5 numbers, since you are dropping them, so they can be dropped before they are completely computed (!!).
If you want to experiment, define yourself a function which is very expensive to compute (say, write fibonacci following the recursive definifion).
fibonacci 0 = 0
fibonacci 1 = 1
fibonacci n = fibonacci (n-1) + fibonacci (n-2)
Then, define
const5 n = 5
and compute
fibonacci 100
and observe how long that actually takes. Then, evaluate
const5 (fibonacci 100)
and see that the result is immediately reached -- the argument was not even computed (!) since there was no need for it.