Clean list comprehension for sampling from list of lists? - haskell

I have a lists of list in Haskell. I want to get all the possibilities when taking one element from each list. What I have currently is
a = [ [1,2], [10,20,30], [-1,-2] ] -- as an example
whatIWant = [ [p,q,r] | p <- a!!0, q <- a!!1, r <- a!!2 ]
This does what I want. However, this is obviously not very good code, and I'm looking for a better way of writing the list comprehension so that no index number (0,1,2) shows up in the code... which is where I'm stuck.
How can I do this?

Using a function (which uses a list comprehension inside), my solution is
combinations :: [[a]] -> [[a]]
combinations [] = []
combinations [l] = map (\ x -> [x]) l
combinations (x:xs) = combine (combinations [x]) (combinations xs)
where combine a b = [ p ++ q | p <- a, q <- b ]
Example:
*Main> combinations [[1, 2, 3], [4, 5, 6]]
[[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]
*Main> combinations [['a', 'b', 'c'], ['A', 'B', 'C'], ['1', '2']]
["aA1","aA2","aB1","aB2","aC1","aC2","bA1","bA2","bB1",...
"bB2","bC1","bC2","cA1","cA2","cB1","cB2","cC1","cC2"]
Edit: of course you can use the sequence function, as was suggested in the comments:
*Main> sequence [['a', 'b', 'c'], ['A', 'B', 'C'], ['1', '2']]
["aA1","aA2","aB1","aB2","aC1","aC2","bA1","bA2","bB1",...
"bB2","bC1","bC2","cA1","cA2","cB1","cB2","cC1","cC2"]

this is obviously not a good code
This is about the best way you can do it, given your constraint that the input is a list of lists.
If you use a different type, e.g. a triple of lists, then you can index structurally. E.g.
Prelude> let x#(a,b,c) = ( [1,2], [10,20,30], [-1,-2] )
Lets you write:
Prelude> [ (p,q,r) | p <- a , q <- b , r <- c ]
[(1,10,-1),(1,10,-2),(1,20,-1)
,(1,20,-2),(1,30,-1),(1,30,-2)
,(2,10,-1),(2,10,-2),(2,20,-1)
,(2,20,-2),(2,30,-1),(2,30,-2)]
Lesson: to avoid indexing, use a type whose structure captures the invariant you want to hold. Lift the dimension of the data into its type.

Related

99 Haskell Questions #9

https://wiki.haskell.org/99_questions/1_to_10
regarding the solution to Question 9
pack :: Eq a => [a] -> [[a]] -- problem 9
pack [] = []
pack (x:xs) = (x:first) : pack rest
where
getReps [] = ([], [])
getReps (y:ys)
| y == x = let (f,r) = getReps ys in (y:f, r)
| otherwise = ([], (y:ys))
(first,rest) = getReps xs
--input
pack ['a', 'a', 'a', 'a', 'b', 'c', 'c', 'a','a', 'd', 'e', 'e', 'e', 'e']
--output
["aaaa","b","cc","aa","d","eeee"]
whats going on here: (x:first), i can see that rest is being passed pack, but i don't understand the bit before that.
getReps is a function specific to each iteration of pack, as it closes over the current values of x and xs.
The first call to pack "aaaabccaadeeee" results in a call to getReps "aaabccaadeeee". getReps will return ("aaa", "bccaadeeee"). Effectively, pack self splits off the first 'a' (the value of x), and getReps separates the rest of the 'a's from the value of xs. Thus, the final "value" of pack "aaaabccaadeeee" is ('a':"aaa") : pack "bccaadeeee".

Understanding the map function with function composition

I have the following Haskell expression:
let increment x = 1 + x
in \xs -> map chr (map increment (map ord xs))
I know that the above expression takes a list, and applies the ord function to each element in the list. For a list of chars, the result would be a list of integers (the ASCII value). The increment function then increments each integer in the list by 1. The chr function then converts each integer back into its corresponding character.
And I also have the following expression:
map chr . map (1+) . map ord
I am trying to figure out whether the above is equivalent to the first expression.
However when I tried the above expression in GHCI, I got an error:
map chr . map (1+) . map ord ['a', 'b', 'c', 'd', 'e']
I am not sure why the expression didn't work. Since function composition is used, wouldn't the expression be evaluated as:
(map chr (map (1+) (map ord ['a', 'b', 'c', 'd', 'e'])))
With map (1+) getting a list as a result of map ord, and map chr getting a list as a result of map (1+)?
Operators (defined as functions with no alphanumeric characters in their name, which are used in infix style) have lower precedence than other functions in Haskell. Therefore your expression:
map chr . map (1+) . map ord ['a', 'b', 'c', 'd', 'e']
is parsed as:
(map chr) . (map (1+)) . (map ord ['a', 'b', 'c', 'd', 'e'])
And this doesn't make any sense - the . operator combines 2 functions, and map ord ['a', 'b', 'c', 'd', 'e'] is not a function, but a list of numbers.
But there are still better alternatives to your correct version with all the nested parentheses. What you want to do is start with the list of characters, and successively map 3 functions over it. That, by definition of function composition, is the same as applying the composition of the 3 map s to it, ie:
(map chr . map (1+) . map ord) ['a', 'b', 'c', 'd', 'e']
which as #chi points out below, would often be written like this, using the function application operator $ (which has lower precedence than any other operator) to avoid the need for any parentheses:
map chr . map (1+) . map ord $ ['a', 'b', 'c', 'd', 'e']
And, because map f . map g is always the same as map (f . g) (this should be obvious when you stop to think about what these expressions mean - it's also the fundamental law the map operation must satisfy in order to make the list type into a Functor), this can be alternatively written as:
map (chr . (1+) . ord) ['a', 'b', 'c', 'd', 'e']
In my opinion this is the best and most readable version.
Although even better, as #chi again points out, is to use that chr . (1+) . ord is equivalent to succ, the built-in function for getting the "next" value of a type that can be enumerated. So you can just write map succ ['a', 'b', 'c', 'd', 'e']

Getting all the diagonals of a matrix in Haskell

The two-dimensional list looks like:
1 | 2 | 3
- - - - -
4 | 5 | 6
- - - - -
7 | 8 | 9
Or in pure haskell
[ [1,2,3], [4,5,6], [7,8,9] ]
The expected output for diagonals [ [1,2,3], [4,5,6], [7,8,9] ] is
[ [1], [4, 2], [7, 5, 3], [8, 6], [9] ]
Writing allDiagonals (to include anti-diagonals) is then trivial:
allDiagonals :: [[a]] -> [[a]]
allDiagonals xss = (diagonals xss) ++ (diagonals (rotate90 xss))
My research on this problem
Similar question here at StackOverflow
Python this question is about the same problem in Python, but Python and Haskell are very different, so the answers to that question are not relevant to me.
Only one This question and answer are in Haskell, but are only about the central diagonal.
Hoogle
Searching for [[a]] -> [[a]] gave me no interesting result.
Independent thinking
I think the the indexing follows a kind of count in base x where x is the number of dimensions in the matrix, look at:
1 | 2
- - -
3 | 4
The diagonals are [ [1], [3, 2], [4] ]
1 can be found at matrix[0][0]
3 can be found at matrix[1][0]
2 can be found at matrix[0][1]
1 can be found at matrix[1][1]
That is similar to counting in base 2 up to 3, that is the matrix size minus one. But this is far too vague to be translated into code.
Starting with universe-base-1.0.2.1, you may simply call the diagonals function:
Data.Universe.Helpers> diagonals [ [1,2,3], [4,5,6], [7,8,9] ]
[[1],[4,2],[7,5,3],[8,6],[9]]
The implementation in full looks like this:
diagonals :: [[a]] -> [[a]]
diagonals = tail . go [] where
-- it is critical for some applications that we start producing answers
-- before inspecting es_
go b es_ = [h | h:_ <- b] : case es_ of
[] -> transpose ts
e:es -> go (e:ts) es
where ts = [t | _:t <- b]
The key idea is that we keep two lists: a rectangular chunk we haven't started inspecting, and a pentagonal chunk (a rectangle with the top left triangle cut out!) that we have. For the pentagonal chunk, picking out the first element from each list gives us another diagonal. Then we can add a fresh row from the rectangular, un-inspected chunk to what's left after we delete that diagonal.
The implementation may look a bit unnatural, but it's intended to be quite efficient and lazy: the only thing we do to lists is destructure them into a head and tail, so this should be O(n) in the total number of elements in the matrix; and we produce elements as soon as we finish the destructuring, so it's quite lazy/friendly to garbage collection. It also works well with infinitely large matrices.
(I pushed this release just for you: the previous closest thing you could get was using diagonal, which would only give you [1,4,2,7,5,3,8,6,9] without the extra structure you want.)
Here is a recursive version, assuming that the input is always well-formed:
diagonals [] = []
diagonals ([]:xss) = xss
diagonals xss = zipWith (++) (map ((:[]) . head) xss ++ repeat [])
([]:(diagonals (map tail xss)))
It works recursively, going from column to column. The values from one column are combined with the diagonals from the matrix reduced by one column, shifted by one row to actually get the diagonals. Hope this explanation makes sense.
For illustration:
diagonals [[1,2,3],[4,5,6],[7,8,9]]
= zipWith (++) [[1],[4],[7],[],[],...] [[],[2],[5,3],[8,6],[9]]
= [[1],[4,2],[7,5,3],[8,6],[9]]
Another version that works on the rows instead of the columns, but based on the same idea:
diagonals [] = repeat []
diagonals (xs:xss) = takeWhile (not . null) $
zipWith (++) (map (:[]) xs ++ repeat [])
([]:diagonals xss)
Compared to the specified result, the resulting diagonals are reversed. This can of course be fixed by applying map reverse.
import Data.List
rotate90 = reverse . transpose
rotate180 = rotate90 . rotate90
diagonals = (++) <$> transpose . zipWith drop [0..]
<*> transpose . zipWith drop [1..] . rotate180
It first gets the main ([1,5,9]) and upper diagonals ([2,6] and [3]); then the lower diagonals: [8,4] and [7].
If you care about ordering (i.e. you think it should say [4,8] instead of [8,4]), insert a map reverse . on the last line.
One another solution:
diagonals = map concat
. transpose
. zipWith (\ns xs -> ns ++ map (:[]) xs)
(iterate ([]:) [])
Basically, we turn
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
into
[[1], [2], [3]]
[[] , [4], [5], [6]]
[[] , [] , [7], [8], [9]]
then transpose and concat lists. Diagonals are in the reversed order.
But that's not very efficient and doesn't work for infinite lists.
Here is one approach:
f :: [[a]] -> [[a]]
f vals =
let n = length vals
in [[(vals !! y) !! x | x <- [0..(n - 1)],
y <- [0..(n - 1)],
x + y == k]
| k <- [0 .. 2*(n-1)]]
For example, using it in GHCi:
Prelude> let f vals = [ [(vals !! y) !! x | x <- [0..(length vals) - 1], y <- [0..(length vals) - 1], x + y == k] | k <- [0 .. 2*((length vals) - 1)]]
Prelude> f [ [1,2,3], [4,5,6], [7,8,9] ]
[[1],[4,2],[7,5,3],[8,6],[9]]
Assuming a square n x n matrix, there will be n + n - 1 diagonals (this is what k iterates over) and for each diagonal, the invariant is that the row and column index sum to the diagonal value (starting with a zero index for the upper left). You can swap the item access order (swap !! y !! x with !! x !! y) to reverse the raster scanning order over the matrix.

Haskell: List combination for Integers

I have a given list, e.g. [2, 3, 5, 587] and I want to have a complete list of the combination. So want something like [2, 2*3,2*5, 2*587, 3, 3*5, 3*587, 5, 5*587, 587]. Since I am on beginner level with Haskell I am curious how a list manipulation would look like.
Additionally I am curious if the computation of the base list might be expensive how would this influence the costs of the function? (If I would assume the list has limit values, i.e < 20)
Rem.: The order of the list could be done afterwards, but I have really no clue if this is cheaper within the function or afterwards.
The others have explained how to make pairs, so I concern myself here with getting the combinations.
If you want the combinations of all lengths, that's just the power set of your list, and can be computed the following way:
powerset :: [a] -> [[a]]
powerset (x:xs) = let xs' = powerset xs in xs' ++ map (x:) xs'
powerset [] = [[]]
-- powerset [1, 2] === [[],[2],[1],[1,2]]
-- you can take the products:
-- map product $ powerset [1, 2] == [1, 2, 1, 2]
There's an alternative powerset implementation in Haskell that's considered sort of a classic:
import Control.Monad
powerset = filterM (const [True, False])
You could look at the source of filterM to see how it works essentially the same way as the other powerset above.
On the other hand, if you'd like to have all the combinations of a certain size, you could do the following:
combsOf :: Int -> [a] -> [[a]]
combsOf n _ | n < 1 = [[]]
combsOf n (x:xs) = combsOf n xs ++ map (x:) (combsOf (n - 1) xs)
combsOf _ _ = []
-- combsOf 2 [1, 2, 3] === [[2,3],[1,3],[1,2]]
So it seems what you want is all pairs of products from the list:
ghci> :m +Data.List
ghci> [ a * b | a:bs <- tails [2, 3, 5, 587], b <- bs ]
[6,10,1174,15,1761,2935]
But you also want the inital numbers:
ghci> [ a * b | a:bs <- tails [2, 3, 5, 587], b <- 1:bs ]
[2,6,10,1174,3,15,1761,5,2935,587]
This uses a list comprehension, but this could also be done with regular list operations:
ghci> concatMap (\a:bs -> a : map (a*) bs) . init $ tails [2, 3, 5, 587]
[2,6,10,1174,3,15,1761,5,2935,587]
The latter is a little easier to explain:
Data.List.tails produces all the suffixes of a list:
ghci> tails [2, 3, 5, 587]
[[2,3,5,587],[3,5,587],[5,587],[587],[]]
Prelude.init drops the last element from a list. Here I use it to drop the empty suffix, since processing that causes an error in the next step.
ghci> init [[2,3,5,587],[3,5,587],[5,587],[587],[]]
[[2,3,5,587],[3,5,587],[5,587],[587]]
ghci> init $ tails [2, 3, 5, 587]
[[2,3,5,587],[3,5,587],[5,587],[587]]
Prelude.concatMap runs a function over each element of a list, and combines the results into a flattened list. So
ghci> concatMap (\a -> replicate a a) [1,2,3]
[1, 2, 2, 3, 3, 3]
\(a:bs) -> a : map (a*) bs does a couple things.
I pattern match on my argument, asserting that it matches an list with at least one element (which is why I dropped the empty list with init) and stuffs the initial element into a and the later elements into bs.
This produces a list that has the same first element as the argument a:, but
Multiplies each of the later elements by a (map (a*) bs).
You can get the suffixes of a list using Data.List.tails.
This gives you a list of lists, you can then do the inner multiplications you want on this list with a function like:
prodAll [] = []
prodAll (h:t) = h:(map (* h) $ t)
You can then map this function over each inner list and concatenate the results:
f :: Num a => [a] -> [a]
f = concat . map prodAll . tails

Generating list of neighbors of a state

I'm generating neighbours of a state in Haskell.
A state is a list of rows. The actions can be performed independently on a row. A function is called on each row which returns a set of neighbours for that row.
Here's an example (I'll let the rows be chars for simplicity):
state = ['a', 'b', 'c']
rowNeighbours a = ['x', 'y']
rowNeighbours c = ['p', 'q']
rowNeighbours _ = []
neighbours should call rowNeighbours on each row and generate a list of states [['x', 'b', 'c'], ['y', 'b', 'c'], ['a', 'b', 'p'], ['a', 'b', 'q']].
I'm having trouble generating this list. The following is what I came up with as a solution.
neighbours state =
[ [x, y, z] | x <- rowNeighbours (state !! 0), y <- [state !! 1], z <- [state !! 2] ] ++
[ [x, y, z] | x <- [state !! 0], y <- rowNeighbours (state !! 1), z <- [state !! 2] ] ++
[ [x, y, z] | x <- [state !! 0], y <- [state !! 1], z <- rowNeighbours (state !! 2) ]
It works, but my actual problem has '6' rows, so this becomes quite inelegant and looks like a non-functional way to do things. I would appreciate any pointers on how to go about doing this, thank you.
I think this'll do what you want:
neighbors (s:tate) = map (: tate) (rowNeighbors s) ++ map (s :) (neighbors tate)
neighbors [] = []

Categories

Resources