Entering a list comprehension into GHCi does not generate a list, the final square brackets are missing, and the console freezes. This is what I have come up with:
[13*x + 3 | x <- [1..], rem (13*x + 3) 12 == 5, mod (13*x + 3) 11 == 0, 13*x + 3 <= 1000]
I believe the problem lies either with x <- [1..], or 13*x + 3 <= 1000. By 13*x + 3 <= 1000 I meant to determine the upper limit of the values x in x <- [1..] can take.
I'm given back a result [341, but it does the second square bracket is missing, and the console freezes.
Your program enters an infinite loop.
The first number is 341, but in order to produce the next number, your program keeps looking through all the subsequent values of x, evaluates all the guards for those values, and checks if all the guards are true. The very last guard, 13*x + 3 <= 1000 never becomes true again, so the program just keeps enumerating values of x forever. It's looking for the next such x for which all guards are true, and as soon as it finds one, it's going to print it. But such x never comes.
If you want the list to end once x*13 + 3 > 1000, you have to use takeWhile:
... | x <- takeWhile (\y -> y*13 + 3 <= 1000) [1..], ...
That way the list will actually stop when it reaches 1000. No more values of x would be produced.
You're giving the compiler way too much credit. It isn't going to carefully analyse your list comprehension in order to deduce that past a certain point there will be no more results, and it should call the list complete. It only does what you tell it to do.
In this case what you told it to do is:
[ 13*x + 3 -- produce numbers of the form 13*x + 3
| x <- [1..] -- by searching all x from [1..]
, rem (13*x + 3) 12 == 5 -- allowing only x that meet this condition
, mod (13*x + 3) 11 == 0 -- and this condition
, 13*x + 3 <= 1000 -- and this condition
]
So it prints [341 and "freezes" because it's still trying to compute the rest of that list. You don't see anything happening, but internally it's drawing ever bigger x from [1..] and diligently checking those conditions to realise that the number shouldn't be included. But it never hits the end of [1..] in order to stop, so it never gets up to printing the ] and waiting for more input.
With your code you are explicitly telling the compiler that you want to search every number in the infinite1 list [1..]. You are then expecting it to notice that 13*x + 3 <= 1000 can only be true for x drawn from a finite prefix of [1..] and thus actually not search the entire list [1..] as you instructed2.
That is a perfectly reasonable thing to want, and I can imagine a system capable of pulling that off (at least with simple conditions like this). So testing it out like this to see if it works is a good idea! However unless someone actually told you that figuring out enumeration upper bounds from conditions in list comprehensions is a feature that GHC can provide, it shouldn't be surprising that it never completes when you tell it to search an infinite list.
For this style of list comprehension (getting all numbers in a range meeting certain conditions) you normally shouldn't use [1..] and then try to impose a stopping condition. Just figure out that the last number that will pass 13*x + 3 <= 1000 and use [1..76] as your generator instead. You can even have Haskell figure it out for you with [1 .. (1000 - 3) div 13].
You use a generator like [1..] when you want to get all numbers of the right form. Then you can use functions like take or takeWhile to get a finite section at the point where you want to use it for something. e.g.
Prelude> let xs = [13*x + 3 | x <- [1..], rem (13*x + 3) 12 == 5, mod (13*x + 3) 11 == 0]
Prelude> takeWhile (<= 1000) xs
[341]
Prelude> take 5 xs
[341,2057,3773,5489,7205]
In fact the simplest and most direct way to express what you want in a single expression is this:
takeWhile (<= 1000) [13*x + 3 | x <- [1..], rem (13*x + 3) 12 == 5, mod (13*x + 3) 11 == 0]
Everything in a list comprehension (except the generator expression) is only talking about a single element at a time. There's just no way to express concepts that are talking about the returned list as a whole, like "stop searching once the returned numbers go out of this range". But that concept is trivial to express outside of list comprehension as a normal function (takeWhile (<= 1000)). Don't feel like you have to shoehorn your entire computation into a single list comprehension.
1 Strictly speaking it's infinite if you're using a type like Integer (which is the type Haskell will pick without any other code using the result to impose other constraints on the type). If you're using Int then it's technically finite, and your list comprehension will eventually end when it "runs out of numbers". [1..] as a list of Int is still impractically vast for an exhaustive search, however.
But if you use a smaller type, like Word16 (needs to be imported from Data.Word) then you can in fact finish your original list comprehension in a practical amount of time. (Though I had to tweak it a little to make sure the 13*x stuff was computed in a larger type so it doesn't overflow)
Prelude> import Data.Word
Prelude Data.Word> [13*x + 3 | x <- [1 :: Word16 ..], let x' = fromIntegral x, rem (13*x' + 3) 12 == 5, mod (13*x' + 3) 11 == 0, 13*x' + 3 <= 1000]
[341]
2 While I'm being pedantic in the footnotes, if your original list comprehension is being evaluated as a list of Int it wouldn't even be valid to just stop after x grows high enough that 13*x + 3 <= 1000 fails for the first time. Try this:
Prelude Data.Word> let x = 768614336404564650 :: Int
Prelude Data.Word> 13*x + 3 <= 1000
True
This happens because Int does in fact have an upper bound, so a large enough Int will overflow back to negative when you multiply it by 13. So when searching [1..] as [Int] the compiler is in fact right to keep looking past x = 77; there are almost certainly more numbers in your original list comprehension if it's [Int], they just take a long time to reach.
Again a good way to demonstrate is to use a smaller finite type, like Word16. If I use your original list comprehension as [Word16] without modifying it to avoid overflow in the conditions, you get this:
Prelude Data.Word> [13*x + 3 | x <- [1..], rem (13*x + 3) 12 == 5, mod (13*x + 3) 11 == 0, 13*x + 3 <= 1000] :: [Word16]
[341,605,209,869,473,77,737]
Even if the compiler was smart enough to know the regions of [1..] that could possibly pass 13*x + 3 <= 1000 condition, it's never going to be able to read your mind and know whether the overflow-produced numbers are solutions you intended or are the result of a bug in your code. It just does what you tell it to do.
Related
Can someone tell me the formal reason why list/arrays and such are considered more secure when it comes to incremental steps i.e (List.fold > loops).
Exampel code in F#
Functional way (list)
let rec sum lst =
match lst with
| [] -> 0
| x::xs -> x + sum xs
Imperative way (incremental)
let sum n m =
let mutable s = 0
for i=n to m do
s <- s + i
s
If by security you mean "safer" -- then I think this will explain it some. To begin with if you're summing a list, a fold should be somewhat safer as it removes the need for the programmer to correctly index the list:
let sum lst =
let mutable s = 0
for i=0 to (List.length lst - 1) do
s <- s + lst.[i]
s
You avoid a lot of pitfalls completely by using the library function:
let sum lst =
let folder acc element =
acc + element
List.fold folder 0 lst
The fold handles all the edge cases for you, in terms of indices, and list length. (note: this could also be done with a List.reduce (+) lst however that does not handle an empty list, where as a fold does).
The short of it all is that it keeps the programmer from making mistakes on silly index math, and keeps the focus on the actual logic of what is being done.
EDIT: I ironically messed up the index logic in my initial post
I am trying to build a list of 0's using list comprehension. But i also want to make an index 1 where i choose in the list. For example myList 5 2 = [0,1,0,0,0] where 5 is the number of elements and 2 is the index.
myList el index = [0 | n <- [1..el], if n == index then 1 else 0]
but this results in an error.
The smallest change that fixes that is
myList el index = [if n == index then 1 else 0 | n <- [1..el]]
Note that what's at the left of | is what generates the list elements. A list comprehension of the form [ 0 | ...] will only generate zeros, and the ... part only decides how long is the resulting list.
Further, in your code the compiler complains because at the right of | we allow only generators (e.g. n <- someList), conditions (e.g. x > 23), or new definitions (let y = ...). In your code the if ... is interpreted to be a condition, and for that it should evaluate to a boolean, but then 1 makes the result a number, triggering a type error.
Another solution could be
myList el index = replicate (index-1) 0 ++ [1] ++ replicate (el-index) 0
where replicate m 0 generates a list with m zeros, and ++ concatenates.
Finally, note that your index is 1-based. In many programming languages, that's unconventional, since 0-based indexing is more frequently used.
I'm working with some code and there seems to be an issue which I can't figure out.
So I've got a method which decrements an input Int by 1 until it hits 5. (I know if i enter less than 1 it would cause an error but i will fix that later)
I have a second function which calls a takes a List as a parameter which calls this function and returns the list of numbers, I want to call length on this list and populate a separate list (I'm not the best at explaining, i'll show with code examples below)
sub 5 = return [1]
sub x =
do
xs <- sub (x - 1)
return (x:xs)
f xs = [ length (sub x) | x<-xs ]
If I call sub 10 on it's own it gives the output [10,9,8,7,6,1], however if I call length on this, it gives the output [1].
In my head i thought the output would be 6, as it has 6 elements in.
Does anyone have any idea why this is happening and/or a way to fix it?
Thanks in advance.
sub doesn't return [10,9,8,6,1] but [[10,9,8,6,1]] (a list of list) therefore the length is 1. You don't need the return. You are in a list monad, return wraps it's value into a list, this why you end up with nested list. Your code should be
sub 5 = [1] -- or return 1
sub x = do
let xs = sub (x -1)
(x:xs)
The problem is that this sub function is written like you were in an imperative language and that return doesn't mean the same thing in Haskell : it means "wrap this thing in a Monad (which Monad depends on the context)". Here since you use length on the result of sub the list [] monad is used and the result is [ [10, 9, 8, 7, 6, 5] ] a list of one element which happen to be a list of 6 elements. mb14 correctly identified that but then corrected only the first case of your function, the second case is also monadic but shouldn't be...
sub 5 = [1]
sub x = x : sub (x - 1)
is the simple code you should be using, you don't need any monad here...
Let's say I want to find a list of (Integer, Integer) where i and j are >= 2, and i + j + 2*i*j < 100:
ghci> take 10 [ (i, j) | i <- [2..], j <- [2..], i * j + 2*i*j < 100]
[(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(2,8),(2,9),(2,10),(2,11)]
However, when I change this function to accept an argument n (rather than 100), it's not terminating for me after ~15 seconds.
ghci> let f n = take 10 [ (i, j) | i <- [2..], j <- [2..], i * j + 2*i*j < n]
ghci> f 5
Interrupted.
If you call f 100 instead of f 5, you'll get the same results as the first example. The problem isn't the fact that it's a function; it's the fact that you're trying to extract the first 10 elements of a filtered infinite list when the filter will never return that many elements.
There are no values of i and j greater than or equal to 2 for which 3*i*j < 5, so the returned list for n=5 should be empty. But Haskell can't determine that it's empty until it's examined all possible values of i and j. As written, that's an infinite number of possibilities. Since it never runs out of possible inputs, and never gets to the desired ten outputs, it never terminates.
The other thing to notice is that the first ten answers to the problem for n=100 all have i=2. If you try a number in between, such 50, you can watch the function generate the first part of the correct answer for that case - specifically, in the case of n=50, the seven elements which have i equal to 2. But after that, despite there being more than the needed three additional solutions to get to ten elements, it hangs. That's becausee those additional solutions all have i > 2. Haskell doesn't find them because it never gets past looking at the "first infinity" cases where i is 2 and j is any number at all.
all_nat x = [ls| sum ls == x]
I'd like to write a function that given an integer x it returns all the lists that the result of their elements when summed is the integer x but I always get the error "not in scope: 'ls' " for both times it apperas. I'm new to haskell. What's the syntax error here?
The problem is that you need to define all used variables somewhere, but ls is undefined. Moreover, it can't be defined automatically, because the compiler doesn't know about the task — how the list should be generated? Ho long can it be? Are terms positive or not, integral or not? Unfortunately your code definition of the problem is quite vague for modern non-AI languages.
Let's help the compiler. To solve such problems, it's often useful to involve some math and infer the algorithm inductively. For example, let's write an algorithm with ordered lists (where [2,1] and [1,2] are different solutions):
Start with a basis, where you know the output for some given input. For example, for 0 there is only an empty list of terms (if 0 could be a term, any number could be decomposed as a sum in infinitely many ways). So, let's define that:
allNats 0 = [[]] --One empty list
An inductive step. Assuming we can decompose a number n, we can decompose any number n+k for any positive k, by adding k as a term to all decompositions of n. In other words: for numbers greater than 0, we can take any number k from 1 to n, and make it the first term of all decompositions of (n-k):
allNats n = [ k:rest --Add k as a head to the rest, where
| k <- [1 .. n] --k is taken from 1 to n, and
, rest <- allNats (n - k)] --rest is taken from solutions for (n—k)
That's all! Let's test it:
ghci> allNat 4
[[1,1,1,1],[1,1,2],[1,2,1],[1,3],[2,1,1],[2,2],[3,1],[4]]
Let's break this up into two parts. If I've understood your question correctly, the first step is to generate all possible (sub)lists from a list. There's a function to do this, called subsequences.
The second step is to evaluate the sum of each subsequence, and keep the subsequences with the sum you want. So your list comprehension looks like this:
all_nat x = [ls| ls <- subsequences [1..x], sum ls == x]
What about
getAllSums x = [(l,r)| l <- partial_nat, r <- partial_nat, l + r == x ]
where partial_nat = [1..x]