I'm very excited with what I've seen of Haskell, but I'm already not quite getting list comprehensions.
If I want to find the truth set of something like:
P(x): x ^ 2 < 3
Why does the expression [x | x ^ 2 < 3] return []? Am I getting the syntax wrong?
You need to provide a source list for x, e.g.
[x | x <- [0.01, 0.02 .. 3], x ^ 2 < 3]
Haskell does not just generate values from a type, you have to provide a source of data.
What you have shown in your question, [x | x ^ 2 < 3], shouldn't even compile. I suspect you have typed this into the interpreter after having defined 'x' at some point. For example:
Prelude> let x = 3
Prelude> [x | x ^ 2 < 3]
[]
In the above the list comprehension reads as 'the list of elements "x" such that the square of "X" is less than three'. Obviously this can only end up with zero or one elements. We can see the case where it produces one element in the below:
Prelude> let x = 1
Prelude> [x | x ^ 2 < 3]
[1]
Your desire to get a set of ALL elements requires you to define an input (I'm ignoring the fact that this is a LIST and not a set - but it is important so if you didn't realize that then look into it). For example, the naturals:
Prelude> take 10 [x | x <- [0..], x ^ 2 < 3]
[0,1^CInterrupted.
This computation is a little closer. For each value in 0, 1, 2... test if its square is less than three and (if so) return it as the next element of the list. Unfortunately, list comprehension preserves no knowledge about the structure of the domain - numbers from 2 upward will be tested (until the end of our input list, which in this case is the max bound of Int) giving it the appearance of non-termination.
Instead, we can define a domain and, knowing the behavior of our predicate, only accept elements while it holds:
Prelude> takeWhile (\x -> x^2 < 3) [0..]
[0,1]
Related
I'm very much a beginner in Haskell, I'm trying to create a tuple of 2 elements, the first being an integer, and the second being a float. Example:
f1 n = [(x, x) | x <- [1 .. n]]
f2 n = [(x, 1 / x) | x <- [1 .. n]]
> f1 5
[(1,1),(2,2),(3,3),(4,4),(5,5)]
> f2 5
[(1.0,1.0),(2.0,0.5),(3.0,0.3333333333333333),(4.0,0.25),(5.0,0.2)]
f1 behaves as expected, returning a list of tuples of two integers.
f2 returns a list of tuples of two floats, but I was expecting it to return a list of tuples of one integer and one float.
How would I preserve the first tuple element type as integer, such that the output of f2 5 would look like: [(1,1.0),(2,0.5),(3,0.3333333333333333),(4,0.25),(5,0.2)]
The reason this happens is that the compiler sees 1/x, which requires not only the result to be floating (Fractional, actually) but also the argument x. This is because the numerical operators in Haskell have all-same-type signatures
(/) :: Fractional a => a -> a -> a
I.e. the compiler infers that x must already have floating type as well, and thus the left element of the tuple ends up as a float.
You can prevent this by dividing not by x itself but instead allowing for conversion:
Prelude> [(x, 1 / fromIntegral x) | x <- [1 .. 9]]
[(1,1.0),(2,0.5),(3,0.3333333333333333),(4,0.25),(5,0.2),(6,0.16666666666666666),(7,0.14285714285714285),(8,0.125),(9,0.1111111111111111)]
Additionally, one thing you should always try when the types don't seem right is to add an explicit signature. This way you can also enforce the computation to be carried out in other, perhaps more suitable types such as Rational:
Prelude> [(x, 1 / fromIntegral x) | x <- [1 .. 9]] :: [(Int, Rational)]
[(1,1 % 1),(2,1 % 2),(3,1 % 3),(4,1 % 4),(5,1 % 5),(6,1 % 6),(7,1 % 7),(8,1 % 8),(9,1 % 9)]
Also, you'll then get a clear-cut compiler error if you try something that doesn't work, instead of silently unexpected results.
Consider the following:
list = [1,3..]
generate n = [compute y | y <- list , (compute y) < n ]
compute a = ... whatever ...
Is it possible to exit the generator before getting to the last element of my list
(e.g. if (compute y > 20)?
I want to save computing power. I only need the elements smaller than n.
I'm new to Haskell. A simple answer might be the best answer.
The wonderful thing about Haskell is that it's lazy. If you said
> let x = generate 100000
then Haskell doesn't immediately calculate generate 100000, it just creates a promise to start calculating it (we normally call this a thunk).
If you want only elements only until compute y > 20, then you can do
> takeWhile (<= 20) (generate 100000)
This is the same semantics that let you do something like
> let nums = [1..] :: [Integer]
This makes a lazy reference to all Integer values from 1 to infinity. You can then do things like
> take 10 $ map (* 10) $ drop 12345 $ map (\x -> x ^ 2 + x ^ 3 + x ^ 4) $ filter even nums
[3717428823832552480,3718633373599415160,3719838216073150080,3721043351301172120,3722248779330900000,3723454500209756280,3724660513985167360,3725866820704563480,3727073420415378720,3728280313165051000]
And while tihs seems like a lot of work, it only calculates the bare minimum necessary to return the 10 elements you requested. The argument to take 10 in this example is still an infinite list, where we first grabbed all the evens, then mapped an algebraic expression to it, then dropped the first 12345 elements, then multiplied all remaining (infinite) elements by 10. Working with infinite structures in Haskell is very common and often advantageous.
As a side note, your current definition of generate will do extra work, you'd want something more like
generate n = [compute_y | y <- list, let compute_y = compute y, compute_y < n]
This way compute y is only calculated once and the value is shared between your filter compute_y < n and the left hand side of the | in the comprehension. Also be aware that when you have a condition in a comprehension, this gets translated to a filter, not a takeWhile:
> -- filter applies the predicate to all elements in the list
> filter (\x -> x `mod` 5 == 0) [5,10,15,21,25]
[5,10,15,20]
> -- takeWhile pulls values until the predicate returns False
> takeWhile (\x -> x `mod` 5 == 0) [5,10,15,21,25]
[5,10,15]
estaLivre lg pls = head [s | (l,s) <- pls, l==lg] == 0
This function receives two lists as parameters. The first one is the coordinates of a chair in a theater. Like (1, 1) row 1, column 1. pls is the description of the chairs in the theater. pls consists of the coordinates of the chair and 1 or 0, wich tells if the chair is taken (1) or if its not (0). Something like this: pls = [((1, 1), 1), ((1, 2), 0)] the chair (1, 1) is taken. The chair (1, 2) is not.
I didn't understand how this woks. head takes the first element of the list and sees if it equals to 0 (is that right?) but s is not the first element. So how does this work?
I've done some tests to see how this works and apparently, head takes the element that's before the '|'. In this case, 's'. One of my tests was to take the head of [y | (x, y) <- xs, x == y^1/2]. It returned the value of y. I did the same thing with [x | (x, y) <- xs, y == x^2] and it returned x. But it's still confusing to me because I was taught that head takes the first element of a list. Can someone explain this to me?
Let's start with the parameters: lg is the position that you want to test to be free and pls is the list of positions, where each position is a tuple (coords,if coords are free then 0 else 1).
The list comprehension is used to pick from the list pls the positions that have the same coords given in input, i.e. lg, and then select only the second part of the tuple, that is if the position is free:
[s | (l,s) <- pls, l==lg]
Because pls is a list, it is possible that more than one element in it satisfies l==lg, for example when pls = [((1,1),0),((1,1),0)] the expression above will return [0,0], and thus you have to use head to extract the first occurrence that satisfies the predicate:
head [s | (l,s) <- pls, l==lg]
This will tell you if that position is free, by returning 0, or taken, by returning 1, and the final test == 0 will convert 0 or 1 into a boolean value.
As side note I would like to say that this function is terrible and unsafe, in particular because it uses head to extract one possible occurrence of the given coordinates. It should be rewritten to use maps and not lists and to use bool instead of int to say if the position is taken or not.
The head function is defined as
head :: [a] -> a
head (x:xs) = x
head [] = error "Prelude.head: empty list"
All it does is grab the first element from the list.
What you're confused about is the list comprehension syntax. This is a syntax that lets you write list operations very cleanly without having to resort to functions like map, filter, or list monadic syntax (that's a topic for another day). In short, if you see something like
[function x | x <- someList, condition x]
This is broadly equivalent to
map function (filter condition someList)
Think of <- as iterating over each element in someList and assigning that value to x, then it checks it against a condition function condition, the builds a list out of it, applying function to each element. This syntax is also useful if you want to iterate over multiple lists, but I'll let you play with it yourself (try out things like [(x, y) | x <- [1..5], y <- [6..10]] in GHCi to see what happens).
So in your case, you have
estaLivre lg pls = head [s | (l,s) <- pls, l==lg] == 0
If we use the rules from above, we can convert this into
estaLivre lg pls = head (map snd $ filter (\(l, s) -> l == lg) pls) == 0
This might be more obvious if the tuple wasn't pattern matched on, you could write your original function as
estaLivre lg pls = head [snd x | x <- pls, fst x == lg] == 0
So the list [s | (l,s) <- pls, l==lg] is going to return a list of all seat occupancies s for the given row/column coordinate lg, then head gets the first element out of that list, and then it's compared to 0.
In my test-exam a question was, what this method does.
dos a = ([x | x <- [2..div a 2], mod a x == 0] == [])
I am new to Haskell but as far as I can say, it checks if the result of dos a = ([x | x <- [2..div a 2], mod a x == 0]) is an empty list. Also x are all numbers of a divided by 2 which have %number == 0. Thus this are all even numbers? It seems like it checks if the number is dividable through 2, if yes -> false, else otherwise. Could anyone explain to me the semantic in detail?
You are close to what is going on. There are several components to understand.
First, [2 .. div a 2] generates a list of numbers from 2 to floor(a / 2).
Next, mod a x == 0 filters out the values from 2 to floor(a / 2) which
divide a (e.g. it finds all the factors of a).
Thus, the list generated by
[x | x <- [2 .. div a 2], mod a x == 0]
contains all the numbers that divide a.
Finally, the == [] checks that
this list is empty (e.g. a has no factors). So, what this function actually
does is to determine whether or not a number is prime by attempting to
generate its factors, which is easy to see when you use dos as the predicate
for filter:
Prelude> let dos a = ([x | x <- [2..div a 2], mod a x == 0] == [])
Prelude> :t dos
dos :: Integral t => t -> Bool
Prelude> filter dos [2 .. 100]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97] -- Prime goodness
It is the basic algorithm to check if a number is prime or not. It traverses over all the numbers from 2 to a/2 and checks if any of it divides a, if the list is empty then it means it has no factors between 2 and a/2 which implies the number is prime.
I can remove all occurences of element in the list:
*Main> let d = [1, 2, 3, 4, 5, 6]
*Main> d
[1,2,3,4,5,6]
*Main> [x | x <- d, not(x == 2)]
[1,3,4,5,6]
I just wondering if there is any possibility to remove only FIRST occurence of element in the list, but using list comprehension?
No, there isn't. The list comprehension
[ x | x <- d, GUARD ]
is equivalent by definition to the following:
let ok x = if GUARD then [x] else []
ok _ = []
in concatMap ok d
By the definition of 'if', GUARD must be a pure boolean expression (i.e. evaluate to True of False alone), so it cannot keep track of state as you map over the list (assuming you're going to play by the rules).
Having said that, there is one way around this that uses comprehensions: zip state into your input list and run a list comprehension on that composite list. This composite list might have a type of something like [(Int, Bool)] where the Bool indicates whether this is the first item in the list. You then do something like:
[ x | (x, isFirst) <- zip d (findFirsts d), not (x == 2 && isFirst)]
where the implementation of findFirsts d is left as an exercise to the reader.
But you wouldn't want to do this in this particular case. It's a bad solution here because it basically means you're going to go through the list at least twice, once to figure out which items are the Firsts, and once to actually filter out the item(s) you don't want. If you implemented findFirsts naively, you might be looking at a bunch more work than even that. Not the right tool for the job!
For certain problems, though, like checking for the head or incorporating the specific position of an item into your results (as hvr has demonstrated), this can be a very effective technique.
Two other ways:
Use monadic computations to carry state as you sequentially iterate through the list. Might be OK for cases where you want to traverse arbitrary or complicated structures, or where your computation is going to be complicated, but in this case, you're better off if you:
Just use a simple recursive function solution, which is what Data.List.delete and deleteBy do.
For the record I wanted to point out that the delete function in the Data.List module provides exactly the behaviour you describe.
So you could cheat a bit and just use delete in your list comprehension:
> let l = [1,2,3,2,1]
> [x | x <- delete 2 l]
[1,3,2,1]
I guess this doesn't count.
...so, I was curious how to do this and here's a solution which doesn't use delete:
-- Removes the first occurrence of '2' in 'l', if any.
[x | (x,y) <- zip l [0..], let idx = elemIndex 2 l, idx == Nothing || y /= fromJust idx]
The idea is to first turn the list into a list of tuples where the second element of each tuple is the index of the element, e.g. "abcba" becomes [('a',0),('b',1),('c',2),('b',3),('a',4)]. Then we take each first element of all tuples for which the second tuple element does not equal the value returned by 'elemIndex' (which returns the position of the first occurance of the given element). For instance, elemIndex 'b' "abca" yields 2, so we take the first elements of all tuples where the second element is not 2. And that yields "acba".
The following removes the element only if occuring in head position:
[ x | (i, x) <- zip [0..] d, if i == 0 then x /= 2 else True ]
(which wasn't the question)
Not directly. List comprehensions are equivalent to using concat and map only. They map elements uniformly - if a is changed to b (or removed, or changed into several elements) then all occurences of a will do the same.
An ugly way would be to tag elements with numbers and search for the first one:
f r x = let x' = zip x [0..]
(_,n) = head [v | v <- x', fst v == r]
in [y | (y,m) <- x', y /= r || m /= n]
First zip can be expressed with LC if you use extension "parallel list comprehensions". This is extremely nonidiomatic, better use explicit recursion or Data.List.delete.