implementing a per-digit counter using the list monad - haskell

So, I was looking at the question here, and built a rather ugly solution for the problem. While trying to clean it up, I started investigating list comprehensions and the list monad. What I decided to do was to implement a per-digit counter using the list monad. Given an input sequence of digits, [1, 2], I wanted to generate an output sequence that looked something like:
[ [ 0, 0],
[ 0, 1 ],
[ 0, 2 ],
[ 1, 0 ],
[ 1, 1 ],
[ 1, 2 ] ]
That is, I'd iterate over all possible values of all elements in the list in that range.
The haskell.org list monad documentation says:
The bound function is applied to all possible values in the input list and the resulting lists are concatenated to produce a list of all possible results.
Great! Looks perfect... Here's the code I wrote to produce the solution:
count :: [Integer] -> [[Integer]]
count [] = []
count (x:xs) =
-- get all possible sequences for the remaining digits
let
remDigits :: [[Integer]]
remDigits = count xs
in
-- pull out a possible sequence for the remaining digits
do nextDigits <- remDigits
-- pull out all possible values for the current digit
y <- [0..x]
-- record that "current digit" : "remaining digits" is
-- a valid output.
return (y:nextDigits)
But calling count with anything produces the empty list, and I don't know why. What am I missing?

count = sequence . map (enumFromTo 0)
Yes, it's really as simple as that. Give it a try :)

even shorter
count = mapM (enumFromTo 0)

For completeness, you can also express the logic as a list comprehension, which is probably the best way to use the list monad for simple functions:
count (x:xs) = [ (y:ys) | y <- [0..x], ys <- count xs ]

First off, you need a base case for the singleton list as an argument. Try this:
count :: [Integer] -> [[Integer]]
count [] = []
count [n] = map (\x -> [x]) [0..n]
count (x:xs) =
do y <- [0..x]
nextDigits <- count xs
return (y:nextDigits)
main = do
print $ count [1]
print $ count [1,2]

Related

Haskell 99 Questions #27

I'm having trouble conceptualizing given answer for problem 27 in haskell's 99 problems https://wiki.haskell.org/99_questions/Solutions/27.
The Problem:
"
Group the elements of a set into disjoint subsets.
a) In how many ways can a group of 9 people work in 3 disjoint subgroups of 2, 3 and 4 persons? Write a function that generates all the possibilities and returns them in a list.
Example:
* (group3 '(aldo beat carla david evi flip gary hugo ida))
( ( (ALDO BEAT) (CARLA DAVID EVI) (FLIP GARY HUGO IDA) )
... )
b) Generalize the above predicate in a way that we can specify a list of group sizes and the predicate will return a list of groups.
"
The answer they give is this:
combination :: Int -> [a] -> [([a],[a])]
combination 0 xs = [([],xs)]
combination n [] = []
combination n (x:xs) = ts ++ ds
where
ts = [ (x:ys,zs) | (ys,zs) <- combination (n-1) xs ]
ds = [ (ys,x:zs) | (ys,zs) <- combination n xs ]
group :: [Int] -> [a] -> [[[a]]]
group [] _ = [[]]
group (n:ns) xs =
[ g:gs | (g,rs) <- combination n xs
, gs <- group ns rs ]
I'm having a lot of trouble understanding how the first section (the section defining the function "combination") operates.
I'm pretty new to haskell too, so explain it to me like I'm in 5th grade.
Any feedback appreciated.
combination 0 xs = [([],xs)]
If we want to choose 0 elements from xs, there is only one way. No elements are taken [] and all the elements xs are left there.
combination n [] = []
Otherwise, we want to choose n (>0) elements. If we want to chose them from the empty list [], there are no ways to do that -- it's impossible.
combination n (x:xs) = ts ++ ds
where
ts = [ (x:ys,zs) | (ys,zs) <- combination (n-1) xs ]
ds = [ (ys,x:zs) | (ys,zs) <- combination n xs ]
Otherwise, we want to choose n (>0) elements from a nonempty list x:xs. There are many ways to do that, which we separate in two groups as follows:
we decide to take the element x among the chosen ones, and we are left with choosing n-1 from xs. This is done in ts, which considers all the ways to choose n-1 elements from xs, and then adds x to the list of "chosen" elements ys.
we decide to drop the element x from the input list, and we are left with choosing n from xs. This is done in ds, which considers all the ways to choose n elements from xs, and then adds x to the list of "dropped" elements zs.
We then output all such combinations using ts++ds.
Function combination takes list and one number. It creates the combination of the list considering the list has to be divided only in two parts. This is simply the original problem reduced only with 2 numbers k and n-k.
It does this using ts and ds lists.
ts is when the first element is in first part and then recursion occurs with remaining list and k-1. ds is where first element is in second part and recursion occurs with k and remaining part. Once remaining part is computed first element is added to it.

Finding "gaps" in a list of numbers

I'm having trouble with going through a list. I made this code which gives me a list of numbers which are evenly divided by the sum of their digits. For example, consider the number 123: 123/6 = 20.5, so it will not be in the list. One the other hand 280 will be on the list, because 280/10 = 28.
let inaHelper x = (floor(x)`mod`10)+ (floor(x/10)`mod`10)+(floor(x/100)`mod`10)
let ina = [x | x <- [1..999] , x `mod` (inaHelper x) == 0 ]
[1,2,3,4,5,6,7,8,9,10,12,18,20,21,24,27,30,36,40,42,45,48,50,54,60,63,70,72,80,81,84,90,100,102,108,110,111,112,114,117,120,126,132,133,135,140,144,150,152,153,156,162,171,180,190,192,195,198,200,201,204,207,209,210,216,220,222,224,225,228,230,234,240,243,247,252,261,264,266,270,280,285,288,300,306,308,312,315,320,322,324,330,333,336,342,351,360,364,370,372,375,378,392,396,399,400,402,405,407,408,410,414,420,423,432,440,441,444,448,450,460,465,468,476,480,481,486,500,504,506,510,511,512,513,516,518,522,531,540,550,552,555,558,576,588,592,594,600,603,605,612,621,624,629,630,640,644,645,648,660,666,684,690,700,702,704,711,715,720,730,732,735,736,738,756,770,774,777,780,782,792,800,801,803,804,810,820,825,828,832,840,846,864,870,874,880,882,888,900,902,910,912,915,918,935,936,954,960,966,972,990,999]
But my problem now is: from the list above I only want the numbers that will not have a "neighbour" within a gap of 5 units. For example, the number 300 will be in the new list because it's neighbors (288 and 306) are not within the 5 unit gap.
I came up it this code:
let rare = [ x | x <- [ina] , ((x-5) >= [ina-1]) && ((x+5) <= [ina+1]) ]
I'm a beginner, can someone help?
An easy, though not very efficient, way would be to make a helper function which checks whether there is an element of a list within a certain range:
hasElemInRange :: (Int,Int) -> [Int] -> Bool
hasElemInRange (lo, hi) xs = -- left as exercise
(hint: you can use the any function)
and then you can include it in your list comprehension:
let rare = [ x | x <- ina, hasElemInRange (x-5,x+5) ina ]
Another idiom that you might consider is zipping a list with its own tail. So you can do:
ghci> let xs = [1,2,3,4,5,6,7]
ghci> zip3 xs (tail xs) (tail (tail xs))
[(1,2,3),(2,3,4),(3,4,5),(4,5,6),(5,6,7)]
Which will give you each element of the list with its "context", the element just before and after. Maybe you can figure out how to use that for what you need.

Enumerate All Finite Sequences of Integers?

I want to write a Haskell list comprehension to enumerate all finite sequences of integers.
I'm pretty sure that this set is countable.
This is what I have so far:
enumIntSeqs = [ (x, [ ( x, [0..x] ) | x <- [ x | x <- [0..x] ] ] ) | x <- [0..] ]
Another idea I have is to somehow list every finite path in the infinite array
Z* X Z* where Z* = {0, 1, -1, 2, -2,...}
This is, indeed, possible. But it is not easy. Imagine you have an enumeration of all integers, an enumeration of all pairs of integers, an enumeration of all triples of integers, etc. Then you need to choose "fairly" from those enumerations to be sure to hit each element of each. A similar problem will arise when you try even to enumerate all pairs of integers. I suggest you start with that problem, and then look into something like Control.Monad.Omega, or perhaps even Control.Monad.Logic.
I am not going to spoil your fun by attempting a full answer, so let me just demonstrate a handful of things through the simplified problem of enumerating all finite, non-empty, sequences of contiguous naturals starting from zero -- something that you seem close to achieving on your own already. The key steps are already amidst your enumIntSeqs, but you don't have to nest list comprehensions like that. If you begin with...
[ {- etc. -} | x <- [0..] ]
... you can generate a new list for each x simply by doing...
[ {- etc. -} | x <- [0..], let ys = [0..x] ]
... and then returning those lists:
[ ys | x <- [0..], let ys = [0..x] ]
(Note that I didn't write ys <- [0..x]. Try to predict what would happen in that case, and then check it in GHCi.)
The separate let definition isn't necessary, nor does it add anything in terms of clarity in this simple comprehension, so we can just write:
[ [0..x] | x <- [0..] ]
And that's it.
Prelude> take 4 $ [ [0..x] | x <- [0..] ]
[[0],[0,1],[0,1,2],[0,1,2,3]]
P.S.: Two other ways of writing the enumeration. Using do-notation...
someIntSeqs = do
x <- [0..]
return [0..x]
... and with a humble fmap (which in this case is the same as map):
Prelude> take 4 $ fmap (\x -> [0..x]) [0..]
[[0],[0,1],[0,1,2],[0,1,2,3]]
Prelude> -- Or, equivalently...
Prelude> take 4 $ (\x -> [0..x]) <$> [0..]
[[0],[0,1],[0,1,2],[0,1,2,3]]
I don't know if this is what you want, because your question wasn't very clear, but given the example that you provided [0,1,-1,-2,2..], I'm going to give a few examples of how to produce a sorted list of integers, and change it according to your needs.
numberline :: Integer -> [Integer]
numberline n = line (-abs n) (abs n) []
where
line 0 0 l = (0:l)
line r s t = r : line (r+1) (s-1) (s:t)
What it does is to ensure that there is a positive and negative number, with the use of -abs and abs as inputs, so that the line function returns them in that order. Then, you only need to map this function to a list of an arbitrary size to get a list of lists with integers ranging from a negative number to its symmetric end.
map numberline [1..2] -- [[-1,0,1],[-2,-1,0,1,2]]
map numberline [1..] -- [[-1,0,1],[-2,-1,0,1,2],[-3,-2,-1,0,1,2,3]..
So how do you change the above piece of code to generate an alternating path between integers as pairs of natural numbers in some array without repeating them?
countable :: Integer -> [Integer]
countable n = count (-abs n) (abs n) []
where
count 0 0 l = (0:l)
count r s t = count (r+1) (s-1) (s:r:t)
The end result being [0,1,-1,2,-2,3,-3] for countable 3. It's not very efficient for big numbers, so you may want to consider a list starting from the argument down to 0 instead of the other way around.
I hope that I helped.

List comprehensions -require base case?

I don't understand why the base case is needed in this:
-- perms :: Ord a => [a] -> [[a]]
perms [] = [[]]
perms xs = [ (x:ps) | x <- xs, ps <- perms (xs \\ [x])]
It seems to me that it should be automatic from the list-comprehension, but then I noticed that:
[ x:y | x<-[], y<-[] ]
evaluates to [], and not [[]], which seems surprising.
Even so, I was also surprised that without the base case it runs, but always gives [], which violates the type signature.
Is there an easy way to trace the execution of a list comprehension? It seems atomic to Debug.Trace.trace.
You can think of <- as use every element from the list in right in the expression in left.
Since [] has no elements the whole list comprehension returns an empty list.
It will be strange if [ x:y | x<-[], y<-[] ] returns [[]] because : takes element and a list. So to generate [[]] y must be [] but then what will be x?
As KennyTM said [] is of type [[a]]. Actually [] is from every type of this kind:
[a] [[a]] [[[a]]] and so on. If it wasn't then there is no way a function to return an empty list.
Anyway it is a very common mistake to forget some brackets and this is why type annotations are necessary.
Let's de-sugar!
[ x:y | x <- [], y <- [] ]
Turns into
do x <- []
y <- []
return (x:y)
Now, more de-sugaring! Yay!
[] >>= \x -> ([] >>= \y -> return (x:y))
iirc, >>= for lists is flip concatMap, and return is simply \x -> [x]
Let's only do a little bit of that replacement.
concatMap (\x -> ([] >>= \y -> return (x:y))) []
There, now do you see? concatMap f [] will obviously evaluate to []. Because concatMap f is just concat . map f. So map f onto the empty list, and then concatenate the results. Except there are no results, so the final evaluation is [].
So it comes down to the meaning of
[ x:y | x<-[], y<-[] ]
The way to read this is, "What are the possible values of x:y, when x has no possible values, and y has no possible values?" Hopefully, it should be clear that in that case, there are no values at all for x:y, since you'd need a value for x and a value for y to get a possibility for x:y, and you have neither.
This general pattern of selecting combinations of possible values for x and y is called a cartesian product, and the word "product" is used in part because the number of possibile combinations is equal to the number of possibilities for x, times the number of possibilities for y. So if there are zero choices for x, and zero choices for y, you can expect 0 * 0 = 0 choices for combinations of the two.
Here's another hint why there is a base case with an empty list. How many permutations are there of n elements? There are n! permutations. And what is 0!? It's 1. So the length of the result list for perm [] has to be 1. The types and the lack of elements of type a forces the result to be [[]]. No other defined value has the right type and length.
If you have a list comprehension of the form:
[ x:y | stuff ]
then you are producing a list whose elements are of the form x:y for some choices of x and y as determined by stuff. [[]] is a list whose elements are not of the form x:y for any x or y, so the former cannot produce the latter.
In expecting [[]] from [ x:y | x <- [], y <- [] ], you seem to be setting x = [] and y = [] and then considering x:y = [[]]. This is wrong for a couple of reasons:
x is coming from xs of type [a], so x has type a, and is not (in general) a list
the result of the list comprehension is a list of x:y elements, not a single one.

List comprehension in Haskell

I've been using the following code to get all combinations of a pre-determined amount of numbers:
getList x = [ [a,b,c] | a <- [1..x], b <- [1..x], c <- [1..x]]
This was fine to begin with, but I'm looking to expand the program to handle very large lists, and I keep thinking there must be a better way to do this. How would I create a function that takes the same parameter x as here, and also another parameter for how many items the sublists have. For four items I would go and modify the code:
getList x = [ [a,b,c,d] | a <- [1..x], b <- [1..x], c <- [1..x], d <- [1..x]]
It doesn't need to be a list comprehension. Thank you for any help.
I believe what you want would be the replicateM function in Control.Monad.
The list monad is based on "trying all possible combinations", and plain replicate creates a list by repeating an item some number of times. So the result of replicateM is, given some list of possible values, a list of all possible ways to select an item from that list some number of times.
For example:
> replicateM 2 [0, 1]
[[0,0],[0,1],[1,0],[1,1]]
> replicateM 3 [0, 1]
[[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
So to extend your function to arbitrary repetitions, you'd use something like:
getListN n x = replicateM n [1..x]
...where your original getList would be equivalent to getListN 3.
In case, anyone likes a non-Monadic-solution to understand to inner workings (although, the soliution via replicateM is great!):
getListN n = foldl (\ass bs -> [ b:as | b <- bs, as <- ass]) [[]] . replicate n
Essentially, this implementation via foldl works exactly in the same way as the replacatM-solution does.

Resources