Related
I am studying for an exam and I am looking at an example of nested list comprehensions from the book "Learn you a Haskell", and I was hoping if anyone could explain me step by step how to analyze it and come out with its output.
let xxs = [[1,2,3],[2,3,4],[4,5]]
[ [ x | x <- xs, even x] | xs <- xxs ]]
Output: ([[2],[2,4],[4]])
[ [ x | x <- xs, even x] | xs <- xxs ]
[ [ x | x <- xs, even x] | xs <- [[1,2,3],[2,3,4],[4,5]] ]
[ [ x | x <- [1,2,3], even x] , [ x | x <- [2,3,4], even x] , [ x | x <- [4,5], even x] ]
[filter even [1,2,3], filter even [2,3,4], filter even [4,5]]
[[2],[2,4],[4]]
Or
[ [ x | x <- xs, even x] | xs <- xxs ]
map (\xs -> [ x | x <- xs, even x] ) xxs
map (\xs -> filter even xs) [[1,2,3],[2,3,4],[4,5]]
[filter even [1,2,3], filter even [2,3,4], filter even [4,5]]
[[2],[2,4],[4]]
Note this isn't the transformation that GHC actually does, just a way of writing it that might help you understand the output.
List comprehensions could have been defined by few identities:
[ f x | x <- [], ... ] === []
[ f x | x <- [y], ... ] === [ f y | {y/x}... ] -- well, actually, it's
-- case y of x -> [ f y | {y/x}... ] ; _ -> []
[ f x | x <- xs ++ ys, ...] === [ f x | x <- xs, ...] ++ [ f x | x <- ys, ...]
[ f x | True, ...] === [ f x | ... ]
[ f x | False, ...] === []
The handling of complex patterns (as opposed to simple variable patterns) is elided, only hinted at, for simplicity. {y/x}... means, y is substituted for x in .... For actual definition, see the Report.
It follows that
[ f x | xs <- xss, x <- xs] === concat [ [f x | x <- xs] | xs <- xss]
and
[ f x | x <- xs, test x ] === map f (filter test xs)
Your expression is equivalent to
[ [ x | x <- xs, even x] | xs <- xxs ] -- `]`, sic!
=
[ f xs | xs <- xxs ] where f xs = [ x | x <- xs, even x]
Which is to say, there's nothing special about a list comprehension being used as a value expression in the definition of f. It looks "nested", but actually, it isn't.
What is nested, are the generator expressions separated by commas:
[ x | xs <- xss, x <- xs ] === concat [ [x | x <- xs] | xs <- xss ]
-- ^^^ nested generator
(the equivalency like we saw above.) So then,
[ [ x | x <- xs, even x] | xs <- [[1,2,3],[2,3,4],[4,5]] ]
=
[ [ x | x <- [1,2,3], even x]] ++ [[ x | x <- [2,3,4], even x]] ++ [[ x | x <- [4,5], even x] ]
=
[ [ x | x <- [1,2,3], even x], [ x | x <- [2,3,4], even x], [ x | x <- [4,5], even x] ]
=
[ [ x | x <- [1], even x]++[ x | x <- [2], even x]++[ x | x <- [3], even x]
, [ x | x <- [2], even x]++[ x | x <- [3], even x]++[ x | x <- [4], even x]
, [ x | x <- [4], even x]++[ x | x <- [5], even x] ]
=
[ [ 1 | even 1]++[ 2 | even 2]++[ 3 | even 3]
, [ 2 | even 2]++[ 3 | even 3]++[ 4 | even 4]
, [ 4 | even 4]++[ 5 | even 5] ]
=
[ []++[ 2 ]++[], [ 2 ]++[]++[ 4 ], [ 4 ]++[] ]
=
[ [2], [2,4], [4] ]
Or, with filter if you'd prefer,
[ [ x | x <- [1,2,3], even x], [ x | x <- [2,3,4], even x], [ x | x <- [4,5], even x] ]
=
[ filter even [1,2,3], filter even [2,3,4], filter even [4,5] ]
=
[ [2], [2,4], [4] ]
I am having trouble finding the correct syntax for manipulating a list of lists.
Here's what I have
> sumLsts :: [[a]] -> [[a]] -> [[a]]
> sumLsts [[]] [[]] = [[]]
> sumLsts [(x:xs):tx] [(y:ys):ty] = [((+) x y) : sumLsts xs ys] : sumLsts tx ty
Here's sample input and output
> sumLsts [[1,1,1], [1,10,20], [-3, -4, -2]] [[3,5,6],[2,3,4],[2,3,2]]
> [[4,6,7],[3,13,24],[-1,-1,0]]
I was thinking that [(x:xs):tx] would have (x:xs) be seen as a single list and tx be seen as the following list. Haskell doesn't seem to agree.
Here is the error message
Couldn't match expected type 'a' with actual type '[[a0]]'
'a' is a rigid type variable bound by
the type signature for:
sumLsts :: forall a. [[a]] -> [[a]] -> [[a]]
In the pattern: x : xs
In the pattern: (x : xs) : tx
In the pattern [(x : xs) : tx]
Relevant bindings include
sumLsts :: [[a]] -> [[a]] -> [[a]]
As is pointed out in the comments on the question, (x:xs) is the pattern for an object of type [a], whether the a there is Int, String, Bool, or even [a] itself like [Int].
In this case your pattern match should be:
sumLsts ((x:xs):tx) ((y:ys):ty) = ...
{- to [[1, 3, 6], [2, 4, 7], [3, 5, 8]], ((x:xs): tx) matches:
x = 1
xs = [3, 6]
tx = [[2, 4, 7], [3, 5, 8]]
-}
However do note that your function is just:
sumLsts = zipWith (zipWith (+))
zipWith pairs two lists together with a joining function, such that
zipWith f [x1, x2, ..., xn] [y1, y2, ..., yn] =
[ f x1 y1
, f x2 y2
, ...
, f xn yn ]
In this case, your outer two lists get paired together so each sublist is an x and y. You're trying to pair those together with addition, so f is another zipWith, this time zipWith (+)
zipWith (zipWith (+)) [[1,1,1], [1,10,20], [-3, -4, -2]] [[3,5,6],[2,3,4],[2,3,2]]
= [ [ 1, 1, 1] `zipWith (+)` [3, 5, 6]
, [ 1, 10, 20] `zipWith (+)` [2, 3, 4]
, [-3, -4, -2] `zipWith (+)` [2, 3, 2]]
= [ [ 1 + 3
, 1 + 5
, 1 + 6]
, [ 1 + 2
, 10 + 3
, 20 + 4]
, [ -3 + 2
, -4 + 3
, -2 + 2] ]
n is the first argument, and a list is the second. The elements can be can selected several times and in different order.
So it will look something like:
com 1 [1,2,3] = [ [1], [2], [3] ]
com 2 [1,2,3] = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
Ive written these and they work but i need a general function
com :: Int -> [t] -> [[t]]
com x [] = []
com 1 ys = [[z]| z <- ys]
com 2 ys = [z:q:[] | z <- ys, q <- ys]
I think it will look something like this:
com x ys
| x < 0 = []
| otherwise qs = [ z:[] | z <- ys ] com (x-1) qs
all help appreciated
You started good:
com :: Int -> [t] -> [[t]]
com x [] = {- [] -} [[]] -- thanks to #cirdec for spotting this
com 1 ys = [ [z] | z <- ys]
com 2 ys = [ [z,q] | z <- ys, q <- ys] -- <<----
now continue with it for a while:
com 3 ys = [ [y,z,q] | y <- ys, z <- ys, q <- ys]
= [ y:[z,q] | y <- ys, z <- ys, q <- ys]
= [ y:[z,q] | y <- ys, [z,q] <- [ [z,q] | z <- ys, q <- ys]] -- <<----
= [ y:r2 | y <- ys, r2 <- [ [z,q] | z <- ys, q <- ys]] -- <<----
= [ y:r2 | y <- ys, r2 <- ...... ]
right? We can always replace equals by equals, in Haskell!
com 4 ys = [ [x,y,z,q] | x <- ys, y <- ys, z <- ys, q <- ys]
= [ x:[y,z,q] | x <- ys, y <- ys, z <- ys, q <- ys]
= ....
= [ x:r3 | x <- ys, r3 <- ...... ]
can you continue this? can you finish up this line of thought?
com n ys | n > 4 = [ x:r | x <- ys, r <- .... (n-1) .... ]
I have a function that returns a list like this:
[ [1, 2, 3], [], [5], [5,6], []]
But I want to replace the empty lists with 0, so that it looks like this
[ [1, 2, 3], [0], [5], [5,6], [0]]
So far I have tried filter and map with little success. Can someone please point me in the right direction?
Here is the code in question:
knightPlace:: [Int] -> [[Int]]
knightPlace n = makeboard n
where
makeboard n = [x | i<-[0..(length n -1 )], x <- [checkPos i]]
-- checkPos add zero
checkPos i = [j+1 | j<-[0..(length n -1 )], queenFilter n i j]
-- filters all rows, cols and diags, also knights
queenFilter n i j = and [n!!(i) == 0 && n!!(k) /=(j+1) && (n!!(k)==0 || (abs(n!!(k)-(j+1))/=abs(i-k))) && (n!!(k)==0 ||not( ((abs(i-k)==2)&& (abs(n!!(k)-(j+1))==1)) ||((abs(i-k)==1)&& (abs(n!!(k)-(j+1))==2)))) | k<-[0..(length n - 1)] ]
Called like
knightPlace [0, 0, 6, 0, 0, 4, 0, 0]
Consider that if you have a function foo that can transform [] to [0] and return every other list untouched, map foo is the final function that you want.
Replace xs with ys in l,
replaceWith :: [a] -> [a] -> [[a]]
replaceWith xs ys l = map (\x -> if x == xs then ys else x) l
In the case here,
replaceWith [] [0] [[1, 2, 3],[],[5],[5,6],[]]
Change your function with
knightPlace n = map (\x -> if null x then [0] else x) $ makeboard n
Also consider using pointfree style
knightPlace = map (\x -> if null x then [0] else x) . makeboard
I do not know what happened with this.
I have a list
L = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
and i need a function that gives me this:
L = [[1, 4, 7],[2, 5, 8],[3, 6, 9]]
until now i have this:
rotar2 [ ] = [ ]
rotar2 l = [map head l] ++ rotar2(map tail l)
and it works but not at all..
it sends me this error:
[[1,4,7],[2,5,8],[3,6,9],[
Program error: pattern match failure: head []
what should i do?
You are repeatedly taking the heads and tails of every list in your function's input. Eventually, one of these lists will only have the empty list left as a tail and attempting to take the head of that empty list will then fail.
rotar2 [[1,2,3],[4,5,6],[7,8,9]]
= [[1,4,7]] ++ rotar2 [[2,3], [5,6], [8,9]]
= [[1,4,7]] ++ [[2,5,8]] ++ rotar2 [[3], [6], [9]]
= [[1,4,7]] ++ [[2,5,8]] ++ [[3,6,9]] ++ rotar2 [[],[],[]]
= [[1,4,7]] ++ [[2,5,8]] ++ [[3,6,9]] ++ [head [],head[],head []] ++ ...
= [[1,4,7],[2,5,8],[3,6,9],[⊥,⊥,⊥],...]
Transpose
The function rotar2 that you are trying to define is usually called transpose and can be implemented rather straightforwardly as
transpose :: [[a]] -> [[a]]
transpose [] = repeat []
transpose (xs : xss) = zipWith (:) xs (transpose xss)
The idea is that a nonempty list of lists, say [[1,2,3],[4,5,6],[7,8,9]], can be transposed inductively by first transposing its tail [[4,5,6],[7,8,9]], yielding [[4,7],[5,8],[6,9]], and then prepending the elements of the head list [1,2,3] to the elements of the transposed tail:
[ 1 : [4,7] , 2 : [5,8] , 3 : [6,9] ]
Hence:
> transpose [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1,4,7],[2,5,8],[3,6,9]]
In the standard libraries, this function is exported by the module Data.List.
You can redefine the transpose function in one line:
transpose = getZipList . traverse ZipList
All the definitions and instances are in the Control.Applicative and Data.Traversable modules. It's the same definition as in the Stefan Holdermans answer modulo typeclasses and wrapping-unwrapping stuff.