Related
In Haskell I'm trying to create a function with the typing Int -> [a] -> [[a]], that generates a list such as: [[0, 0], [0, 1], [1, 0], [1, 1]] where each element in the smaller lists can take the value of either 1 or 0. Each of the smaller lists has the same size, which in this case is 2. If the size of the smaller lists was 3, I would expect to get the output [[0,0,0], [0,0,1], [0,1,0], [1,0,0], [1,1,0], [0,1,1], [1,0,1], [1,1,1]]
I've looked in to the permutations function, but this does not achieve exactly what I want. I believe there is also a variate function, but I cannot access this library.
Rather than the exact function (which would also be useful), what would be the process to generate such a list?
As oisdk mentions in a comment, a more general version of this exact function is already defined, with the name Control.Monad.replicateM:
Prelude> import Control.Monad (replicateM)
Prelude Control.Monad> 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]]
We can use the list monad for this:
example :: [[Int]]
example = do
x <- [0,1]
y <- [0,1]
pure [x,y]
ghci> example
[[0,0],[0,1],[1,0],[1,1]]
Play with this. Then you should be able to combine it with recursion on n to create the function you need.
I'm not sure I understood the specification, but from the examples, one possible definition is
lists :: Int -> [[Int]]
lists 0 = [[]]
lists n = map (0:) xss ++ map (1:) xss
where xss = lists (n-1)
-- λ> lists 2
-- [[0,0],[0,1],[1,0],[1,1]]
-- λ> lists 3
-- [[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
Another definition, using comprehension instead of map, is
lists :: Int -> [[Int]]
lists 0 = [[]]
lists n = [x:xs | x <- [0,1], xs <- lists (n-1)]
-- λ> lists 2
-- [[0,0],[0,1],[1,0],[1,1]]
-- λ> lists 3
-- [[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
You can use the sequence function.
Like this:
λ>
λ> :t sequence
sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
λ>
λ> let { allLists :: Int -> [a] -> [[a]] ; allLists n xs = sequence $ replicate n xs ; }
λ>
λ> allLists 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]]
λ>
I'm a Haskell beginner,
I have a function
func :: Num a => [a] -> [a]
func [] = []
func (x:xs) = x + func xs
Each recursion I want to append the value to a list for my output. This function will sum consecutive indexes in a list so that the input [1, 2, 3, 4] produces [1, 3, 6, 10].
How do I append the value generated each time to my list?
Your problem here isn't how to append, but rather how to calculate the value in the first place. Each item needs to be substituted with a sum of itself with all the items preceding it.
Here is one way to do it:
Prelude> func (x:xs) = x:map (+ x) (func xs); func [] = []
Prelude> func [1, 2, 3, 4]
[1,3,6,10]
How does this work? We're given a list that starts with the element x and has the remaining elements xs. We want to increment every item in xs by x, after recursively applying the algorithm to xs.
This is what x:map (+ x) (func xs) does. It reads as "prepend x to the result of mapping every element in func xs through an increment by x".
E.g. for [1, 2, 3, 4], we want 1 to be added to every member of the result of recursively applying the algorithm to [2, 3, 4], then prepended. For [2, 3, 4] we want 2 to be ... to [3, 4]. And so on, until eventually for [4] we want 4 to be added and prepended to the result of applying the algorithm to [].
This is where our base case (func [] = []) kicks in: the algorithm is defined so that it returns an empty list unchanged. Hence func [4] is [4], func [3, 4] is [3, 7], and you keep incrementing and prepending until you get [1,3,6,10].
I think in this particular case, you could use scanl1 like:
scanl1 (+) [1,2,3,4] -- [1,3,6,10]
When iterating over lists, we often use folds, which is a way of reducing the list to a particular value.
There's also another type of operation, which is a fold that collects all results along the way, and that's called a scan (from the docs):
scanl = scanlGo
where
scanlGo :: (b -> a -> b) -> b -> [a] -> [b]
scanlGo f q ls = q : (case ls of
[] -> []
x:xs -> scanlGo f (f q x) xs)
So the scan takes three arguments: a function that takes two values and returns a value, a starter value, and a list of values.
The scan will then return a list.
Thus, what you need is a function that takes two values and returns something of the same type as the first (it's okay if both are the same). Binary addition would work here: +.
You also need a value to start off with (the b, which is the second argument to our function), and 0 is the identity for integer addition, so we should use that.
Finally, we pass your list to get the result.
Try to figure out how to write you function as a fold and then as a scan and you will discover the answer.
I have list of lists of Int and I need to add an Int value to the last list from the list of lists. How can I do this? My attempt is below
f :: [[Int]] -> [Int] -> Int -> Int -> Int -> [[Int]]
f xs [] cur done total = [[]]
f xs xs2 cur done total = do
if total >= length xs2 then
xs
else
if done == fib cur then
f (xs ++ [[]]) xs2 (cur + 1) 0 total
else
f ((last xs) ++ [[xs2!!total]]) xs2 cur (done + 1) (total + 1)
The problem is:
We have a list A of Int
And we need to slpit it on N lists B_1 ,..., B_n , length of B_i is i-th Fibonacci number.
If we have list [1 , 2 , 3 , 4 , 5 , 6 , 7] (xs2 in my code)
The result should be [[1] , [2] , [3 , 4] , [5 , 6 , 7]]
The easy way to deal with problems like this is to separate the problem into sub-problems. In this case, you want to change the last item in a list. The way you want to change it is by adding an item to it.
First let's tackle changing the last item of a list. We'll do this by applying a function to the last item, but not to any other items.
onLast :: [a] -> (a -> a) -> [a]
onLast xs f = go xs
where
go [] = []
go [x] = [f x]
go (x:xs) = x:go xs
You want to change the last item in the list by adding an additional value, which you can do with (++ [value]).
Combining the two with the value you want to add (xs2!!total) we get
(onLast xs (++ [xs2!!total]))
f :: [[Int]] -> Int -> [[Int]]
f [] _ = []
f xs i = (take n xs) ++ [[x + i | x <- last xs]]
where n = (length xs) - 1
last = head . (drop n)
For example,
*Main> f [[1, 2, 3], [], [4, 5, 6]] 5
[[1,2,3],[],[9,10,11]]
*Main> f [[1, 2, 3]] 5
[[6,7,8]]
*Main> f [] 3
You approach uses a do block, this is kind of weird since do blocks are usually used for monads. Furthermore it is rather unclear what cur, done and total are doing. Furthermore you use (!!) :: [a] -> Int -> a and length :: [a] -> Int. The problem with these functions is that these run in O(n), so it makes the code inefficient as well.
Based on changed specifications, you want to split the list in buckets with length the Fibonacci numbers. In that case the signature should be:
f :: [a] -> [[a]]
because as input you give a list of numbers, and as output, you return a list of numbers. We can then implement that as:
f :: [a] -> [[a]]
f = g 0 1
where g _ _ [] = []
g a b xs = xa : g b (a+b) xb
where (xa,xb) = splitAt b xs
This generates:
*Main> f [1,2,3,4,5,6]
[[1],[2],[3,4],[5,6]]
*Main> f [1,2,3,4,5,6,7]
[[1],[2],[3,4],[5,6,7]]
*Main> f [1,2,3,4,5,6,7,8]
[[1],[2],[3,4],[5,6,7],[8]]
*Main> f [1,2,3,4,5,6,7,8,9]
[[1],[2],[3,4],[5,6,7],[8,9]]
The code works as follows: we state that f = g 0 1 so we pass the arguments of f to g, but g also gets an 0 and a 1 (the first Fibonacci numbers).
Each iteration g checks whether we reached the end of the list. If so, we return an empty list as well. Otherwise we determine the last Fibonacci number that far (b), and use a splitAt to obtain the first b elements of the list we process, as well as the remainder. We then emit the first part as head of the list, and for the tail we calculate the next Fibonacci number and pass that to g with the tail of splitAt.
Lets say I have nested lsit: [1, [2, 3, 4], [5, [6]]] and I want to count how many elements it has. In this case it is six elements. I have written such code for doing this:
totalElems :: [a] -> Int
totalElems (x:xs) = case (x, xs) of
(_, []) -> 0
(y:ys, _) -> 1 + totalElems ys + totalElems xs
(_, _) -> 1 + totalElems xs
But I've got an error:
a.hs:4:42:
Couldn't match expected type ‘a’ with actual type ‘[a0]’
‘a’ is a rigid type variable bound by
the type signature for totalElems :: [a] -> Int at a.hs:1:15
Relevant bindings include
xs :: [a] (bound at a.hs:2:15)
x :: a (bound at a.hs:2:13)
totalElems :: [a] -> Int (bound at a.hs:2:1)
In the pattern: y : ys
In the pattern: (y : ys, _)
In a case alternative:
(y : ys, _) -> 1 + totalElems ys + totalElems xs
How I can do this in Haskell?
You can't make freeform lists-within-lists like that in Haskell. Dynamically typed langues will tolerate silliness like that, but strongly-typed Haskell won't.
1 is of type Int, and [2,3,4] is of a different type [Int]. Things in a list have to be of the same type.
However, you could do something like this:
data Nest a = Elem a | List [Nest a]
example ::Nest Int
example = List [Elem 1, List [Elem 2, Elem 3, Elem 4], List [Elem 5, List [Elem 6]]]
countNest :: Nest a -> Int
countNest (Elem x) = 1
countNest (List xs) = sum $ map countNest xs
Let's say I have nested lsit: [1, [2, 3, 4], [5, [6]]]
You can't have that list. It won't type-check. Try typing it by itself in GHCi; it'll just spit an error message at you. Since this input can't exist in the first place, trying to write a function to process it is a doomed endeavor.
Instead, you need to define a custom data type for this. See the other answers.
As others have said, the simplest way to do this is with a different data structure, like the tree NovaDenizen defined. However, just so you know, Haskell's type system enables various ways of creating "lists" in which the elements have different types : see https://wiki.haskell.org/Heterogenous_collections
I want to do something like
[(x, y, x+y) | (x,y) <- original]
But of course, this will return something like:
[(0, 0, 0), (0, 1, 1), (1, 1, 2)]
What I want is something like:
[0, 0, 0, 0, 1, 1, 1, 1, 2]
I am quite new to Haskell, and unfamiliar with its idioms. How can I accomplish this in Haskell?
First, a diatribe on types. You are drawing the pair (x,y) from a list named original. Original must be a list of pairs, original :: [(a,b)], such as [(1,6), (4,9)]. You then construct a tuple for each element, hence your result of a list of tuples. I am going by the guess that you never wanted any tuples but actually want some number of elements of the list to be combined by your function and concatenate the results into a new list.
You might looking for the concatMap function:
> :t concatMap
concatMap :: (a -> [b]) -> [a] -> [b]
> concatMap (\x -> [x,x+1,x+7]) [1,2,3]
[1,2,8,2,3,9,3,4,10]
If you actually want to consume two (or more) elements at once then there are a few missing details, such as what to do if you have an odd number of elements and weather or not elements repeat (so you see [1,2,3] as two inputs 1,2 and 2,3).
If elements repeat then this is just a concatMap and a zip:
> let ls = [1,2,3] in concatMap (\(x,y) -> [x,y,x+y]) (zip ls (drop 1 ls))
[1,2,3,2,3,5]
But if you want to see them as [1,2] and [3] then you're best off writing your own function:
func [] = []
func [x] = [[x]] -- What do you want with the odd remaining element?
func (x:y:rest) = [x,y,x+y] : func rest
> concat (func [1,2,3])
[1,2,3,3]
Looks like you're just making a non-deterministic choice -- just what list comprehensions were made for!
[v | (x,y) <- original, v <- [x, y, x+y]]
You can for example create a list of lists and then use concat to flatten it.
concat [[x, y, x+y] | (x, y) <- original]