Haskell dot dot notation on list - unexpected output - haskell

One of the questions that came up in one of my lectures was the following:
trips :: [(Int, Int, Int)]
trips = [ (x,y,z) | z <- [2..], y <- [2..z-1], x <- [2..y-1] ]
What is the first five elements output?
Now I thought I was aware how dot dot notation worked, but when I put the above into a compiler the output is:
(2, 3, 4), (2, 3, 5), (2, 4, 5), (3, 4, 5), (2, 3, 6) etc.
How does this happen?
I thought if things begun with [2..] then all the subsequent lists would begin with two? z is defined as [2..] yet it never once displays 2 as the third int. I'm obviously missing something here but I'm not entirely sure what.

[ (x,y,z) | z <- [2..], y <- [2..z-1], x <- [2..y-1] ] =
[ (x,y,2) | y <- [2..2-1], x <- [2..y-1] ] ++
[ (x,y,3) | y <- [2..3-1], x <- [2..y-1] ] ++
[ (x,y,4) | y <- [2..4-1], x <- [2..y-1] ] ++
... =
[ (x,y,2) | y <- [2..1], x <- [2..y-1] ] ++
[ (x,y,3) | y <- [2..2], x <- [2..y-1] ] ++
[ (x,y,4) | y <- [2..3], x <- [2..y-1] ] ++
... =
[ (x,y,2) | y <- [], x <- [2..y-1] ] ++
[ (x,y,3) | y <- [2], x <- [2..y-1] ] ++
[ (x,y,4) | y <- [2,3], x <- [2..y-1] ] ++
...
Note the range y <- [2..2-1] i.e. y <- [2..1] i.e. y <- []. Because of this, there are no triples (x,y,2) to generate.
Similarly, when y is 2, the range z <- [2..y-1] will generate nothing, and we do not get triples of the form (x,2,3).

Related

List Comprehension with list of lists

I have problems to understand the following piece of code:
treePositions :: Tree a -> [[Int]]
treePositions (Node _ ts) =
[] : [ (i : is ) | i <- [0..(length ts - 1)],
is <- treePositions (index ts i) ]
This function would calculate any valid paths to a position in the given tree, where for every node the edges are marked with 0..lastOutgoingEdge.
If I understood it right the index function would return the node at Index i in the node list of the tree.
index :: [a] -> Int -> a
index :: [a] -> Int -> a
index [] i = error "invalid index"
index (x:xs) 0 = x
index (x:xs) i = ith xs (i-1)
Now for given trees:
t1 = Node "a" [
Node "b" [
Node "c"[],
Node "d"[]
]
]
t2 = Node "z" []
the function would return:
treePositions t1 == [ [], [0], [0,0], [0,1] ]
treePositions t2 == [ [] ]
What I don't understand is this part:
[] : [ (i : is ) | i <- [0..(length ts - 1)],is <- treePositions (index ts i) ]
My thoughts:
If I have x|x <- [0..10], x < 2. This would translate in "take every x in [0..10] for which x < 2 applies. So if I would take every i in [0..(length ts - 1)], how would this then return lists for a condition?
In your case, the part after the comma is not a condition, but a second generator. Simplified, the notation looks like this:
> [ (a, b) | a <- [1..3], b <- [1..2] ]
> [(1,1),(1,2),(2,1),(2,2),(3,1),(3,2)]
The example compherension above means the following:
go through list [1..3], and for every element of it,
go through list [1..2], and for every element of it,
produce a tuple
Further, a generator can depend on elements of previous generators, e.g.:
> [ (a, b) | a <- [1..3], b <- [1..a] ]
> [(1,1),(2,1),(2,2),(3,1),(3,2),(3,3)]
So in your case:
[ (i : is ) | i <- [0..(length ts - 1)],is <- treePositions (index ts i) ]
the logic is this:
for every i in 0..(length ts - 1),
go through every is in treePositions (index ts i),
and produce i : is as result

What does pipe symbol mean?

The following is the haskell comprehensions, what I don't understand is the pipe symbol. What does it mean and what is its role in the function?
boomBangs xs = [ if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]
ghci> let xxs = [[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]]
ghci> [ [ x | x <- xs, even x ] | xs <- xxs]
[[2,2,4],[2,4,6,8],[2,4,2,6,2,6]]
Its expression/syntax for list comprehensions. An easy example is the following,
import Data.Char (toUpper)
[toUpper c | c <- s]
You pass a string (list of chars), [ s ], "Hello", to the generator [ c <- s ] , this feeds each character of s to the left-hand expression [ toUpper c ], building a new list. The result of this list comprehension would be "HELLO".

Cartesian plane for 3 cards and 4cards of deck in Haskell

The following code runs for 2cards of a deck and gives cartesian plane such that no duplicates are there.
allcards = [minBound..maxBound] :: [Card]
cartesianplane=[ [x ,y] | x <- allcards, y <- allcards, x < y ]
How can I do the same for 3 cards and 4cards such that no duplicates are there.
Here's a way to recursively generate the sets:
-- an example set of cards:
data Card = A | T | J | Q | K
deriving (Show, Read, Eq, Ord, Bounded, Enum)
next intv a
| a == maxBound = []
| otherwise = intv (succ a)
interval a = [ a .. ]
interval2 a = [ [x,y] | x <- interval a, y <- next interval x ]
interval3 a = [ x:y | x <- interval a, y <- next interval2 x ]
interval4 a = [ x:y | x <- interval a, y <- next interval3 x ]
interval5 a = [ x:y | x <- interval a, y <- next interval4 x ]
E.g.:
interval A = [A,T,J,Q,K]
interval2 A = [[A,T],[A,J],[A,Q],[A,K],[T,J],[T,Q],[T,K],[J,Q],[J,K],[Q,K]]
interval3 A = [[A,T,J],[A,T,Q],[A,T,K],[A,J,Q],[A,J,K],[A,Q,K],[T,J,Q],[T,J,K],[T,Q,K],[J,Q,K]]
interval4 A = [[A,T,J,Q],[A,T,J,K],[A,T,Q,K],[A,J,Q,K],[T,J,Q,K]]
interval5 A = [[A,T,J,Q,K]]

List-comprehension output not what I assumed

I assume its simple as its in a past paper of my university but the function is:
[(x,y) | x <- [0..2], y<-[0,x])
and the output
[(0,0),(0,0),(1,0), (1,1), (2,0), (2,2)]
The (2,0) confuses me, if y maps to 0 to x whilst x is equal to 1 = (1,1) wouldnt it be
[(0,0),(0,0),(1,0), (1,1), **(2,1)**, (2,2)]
or is it because due to the y using all its numbers in its list [0,1] it reverts back to 0?
case [(x,y) | x <- [0..2], y<-[0,x]]
[0,x] is:
[0,0] for x=0
[0,1] for x=1
[0,2] for x=2
so if you pair each of those ys up with the corresponding x you get:
[(0,0),(0,0)] -- x = 0
++ [(1,0),(1,1)] -- x = 1
++ [(2,0),(2,2)] -- x = 2
which yields your given output
note: [0,2] has length 2 and is quite different from [0..2] which has length 3 and contains 1
case [(x,y) | x <- [0..2], y<-[0..x]]
it's not that different - [0..x] is:
[0] for x=0
[0,1] for x=1
[0,1,2] for x=2
and if you pair each of those ys up with the corresponding x you get
[(0,0))] -- x = 0
++ [(1,0),(1,1)] -- x = 1
++ [(2,0),(2,1),(2,2)] -- x = 2
which then would give you the result
[(0,0),(1,0),(1,1),(2,0),(2,1),(2,2)]

Haskell List Comprehension

I get the error "Not in scope: x" when doing as follows...
blanks :: Sudoku -> [Pos]
blanks (Sudoku su) = [ fst x | x <- posSud | isBlank (snd x) ]
where
isBlank Nothing = True
isBlank _ = False
posSud = zip ixPos (concat su)
ixPos = zip ixRows ixCols
ixCols = concat (replicate 9 [0..8])
ixRows = [floor (x / 9) | x <- [0..81]]
however, if I remove the guard of the 2:nd line GHCI compiles without giving me any errors.
Can you help me understand what I'm doing wrong?
try [ fst x | x <- posSud , isBlank (snd x) ]

Resources