99 Haskell Questions #9 - haskell

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".

Related

How can I write the following haskell code with higher order functions?

The following code represents a function which takes a list as an input and then combines subsequent repetitions of the same value into a sublist.
for example : pack ['a','a','b','b','b','a'] = [['a','a'], ['b','b','b'], ['a']]
pack :: [Char] -> [[Char]]
pack (x:xs) = ys : pack zs
where
(ys, zs) = takeall x (x:xs)
takeall _ [] = ([], [])
takeall x (y:ys)
| x == y = let (us, vs) = takeall x ys
in (y:us, vs)
| otherwise = ([], (y:ys))
I found this code in sample solution. I'm still a beginner at haskell but i've seen the similar problem once as an example for an algorithm in C language.while solving this problem it came to my mind to write the code with the help of higher order functions.I thought the combination of foldl,filter and concatMap could be a good solution for this problem, however i'm not quite sure about filter.I wanted to write a function for filter which goes through the list and compares each element with it's neighbour elements and if they are eqaul returns true. Writing a function like that could be easy but how should i combine it with other functions of higher order so the things that are true come to a list together?
How do you solve this problem with higher order functions?
Firstly, your takeall function can be replaced with the span function from Prelude:
pack :: [Char] -> [[Char]]
pack (x : xs) = ys : pack zs
where
(ys, zs) = span (== x) (x : xs)
pack [] = []
Then, you can get rid of the explicit recursion using unfoldr:
import Data.List (unfoldr)
pack2 :: [Char] -> [[Char]]
pack2 = unfoldr go
where
go (x : xs) = Just $ span (== x) (x : xs)
go [] = Nothing
main :: IO ()
main = do
print $ pack ['a', 'a', 'b', 'b', 'b', 'a']
print $ pack2 ['a', 'a', 'b', 'b', 'b', 'a']
Output:
["aa","bbb","a"]
["aa","bbb","a"]

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']

Keep track of loop without a counter

Say, I got a list which length can be odd or even. Every iteration , I remove two items from the list. If there is one or no item at the end, I end the execution.
If I store (length list)/2 every loop, I will get e.g. [5,4,3...] for a list of length 10.
But what I want is [1,2,3,...] and I couldn't figure out a relationship between the list size and this sequence...
Is there a way to achieve this without having a variable storing the current count?
i.e. with func :: [Int] -> [Int] only
You can certainly do this without changing the type signature of func :: [Int] -> [Int]: have func call a different function, which takes an extra argument that is the counter you were talking about:
func :: [Int] -> [Int]
func = go 0
where go _ [] = []
go _ [x] = []
go n (a:b:xs) = n : a : b : go (succ n) xs
func [11,12..20]
[0,11,12,1,13,14,2,15,16,3,17,18,4,19,20]
If you are determined to do this without managing the counter variable yourself, you can do something more contorted, such as zipping your input list into 3-tuples (a,b,n), where a and b are pairs of items from your input list and n comes from [1,2..].
pairs :: [a] -> [(a,a)]
pairs [] = []
pairs [_] = []
pairs (a:b:xs) = (a,b) : pairs xs
func' :: [Int] -> [Int]
func' xs = concat $ zipWith (\n (a,b) -> [n,a,b]) [1,2..] $ pairs xs
func' [11,12..20]
[1,11,12,2,13,14,3,15,16,4,17,18,5,19,20]
This is quite a bit less readable in my opinion, and I would suggest you just do the easy, obvious thing in my first snippet.
Ok, here's another solution:
func :: [a] -> [Int]
func (_:_:as) = 1 : map (+1) (func as)
func _ = []
I'm a bit unclear what you want the base cases to be, so I guessed you wanted func [] = [] and func [_] = []. Correct me if I'm wrong, please.
Working through your 10 element list example:
func ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] =
1 : map (+1) (func ['c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']) =
1 : map (+1) (1 : map (+1) (func ['e', 'f', 'g', 'h', 'i', 'j'])) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (func ['g', 'h', 'i', 'j']))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (func ['i', 'j'])))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (func []))))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) [])))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : [])))) =
1 : map (+1) (1 : map (+1) (1 : map (+1) (1 : 2 : []))) =
1 : map (+1) (1 : map (+1) (1 : 2 : 3 : [])) =
1 : map (+1) (1 : 2 : 3 : 4 : [])) =
1 : 2 : 3 : 4 : 5 : []) =
[1,2,3,4,5]

Clean list comprehension for sampling from list of lists?

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.

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 [] = []

Resources