How to find length of lists in lists in haskell? [duplicate] - haskell

This question already has an answer here:
How do we partition list in Haskell by a separator element of the list?
(1 answer)
Closed 2 years ago.
snoc :: [a] -> a -> [a]
snoc [] a = [a]
snoc (h : t) a = h : t `snoc` a
lsplit :: Eq a => a -> [a] -> [[a]]
lsplit sep l = lsplit l []
where
lsplit (h : t) acc | sep == h = acc : lsplit t []
lsplit (h : t) acc = lsplit t (acc `snoc` h)
lsplit [] acc = [acc]
This is my code and given below is an example of the running of my code :
> lsplit 0 [1,2,3,0,4,5]
[[1,2,3],[4,5]]
I need to find the length of the lists in lists. for example,
the length of the lists in lists would be [3,2] for the above code.
How could I do this in Haskell?

map the length function onto it:
> map length [[1, 2, 3], [4, 5]]
[3, 2]

Related

Trouble understanding the behavior of `foldr` and `map` in Haskell

I have a function prefixes that, given [1, 2, 3], returns the prefixes [[1], [1, 2], [1, 2, 3]]. It is defined as follows:
prefixes :: Num a => [a] -> [[a]]
prefixes = foldr (\x acc -> [x] : (map ((:) x) acc)) []
I have spent nearly two days trying to understand why this works. When I debug this in my head, I imagine this for prefixes [1, 2, 3]:
foldr call|__________________________________________________________________________
1 | [1] : (map ((:) 1) [])
|
| where x = 1 and acc = []
| returns acc = [[1]]
|
2 | [2] : (map ((:) 2) [[1]])
|
| where x = 2 and acc = [[1]]
| and (map ((:) 2) [[1]])
| returns acc = [[1, 2]]
| and [2] : [[1, 2]]
| returns [[2], [1, 2]]
|
3 | [3] : (map ((:) 3) [[2], [1, 2]])
|
| where x = 3 and acc = [[2], [1, 2]]
| and (map ((:) 3) [[2], [1, 2]])
| returns acc = [[2, 3], [1, 2, 3]]
| and [3] : [[2, 3], [1, 2, 3]]
| returns [[3], [2, 3], [1, 2, 3]]
|
And then the function terminates and returns [[3], [2, 3], [1, 2, 3]]. But obviously that is not happening. It returns [[1], [1, 2], [1, 2, 3]].
In Ghci, I find this:
Stopped in Main.prefixes, ex.hs:21:20-63
_result :: [a] -> [[a]] = _
[ex.hs:21:20-63] *Main> :step
Stopped in Main.prefixes, ex.hs:21:37-59
_result :: [[Integer]] = _
acc :: [[Integer]] = _
x :: Integer = 1
[ex.hs:21:37-59] *Main> :step
[[1]
Stopped in Main.prefixes, ex.hs:21:44-58
_result :: [[Integer]] = _
acc :: [[Integer]] = _
x :: Integer = 1
[ex.hs:21:44-58] *Main> :step
Stopped in Main.prefixes, ex.hs:21:37-59
_result :: [[Integer]] = _
acc :: [[Integer]] = _
x :: Integer = 2
[ex.hs:21:37-59] *Main> :step
,
Stopped in Main.prefixes, ex.hs:21:49-53
_result :: [Integer] -> [Integer] = _
x :: Integer = 1
[ex.hs:21:49-53] *Main> :step
[1,2]
Stopped in Main.prefixes, ex.hs:21:44-58
_result :: [[Integer]] = _
acc :: [[Integer]] = _
x :: Integer = 2
[ex.hs:21:44-58] *Main> :step
Stopped in Main.prefixes, ex.hs:21:37-59
_result :: [[Integer]] = _
acc :: [[Integer]] = _
x :: Integer = 3
[ex.hs:21:37-59] *Main> :step
,
[1Stopped in Main.prefixes, ex.hs:21:49-53
_result :: [Integer] -> [Integer] = _
x :: Integer = 2
[ex.hs:21:49-53] *Main> :step
,2,3]
Stopped in Main.prefixes, ex.hs:21:44-58
_result :: [[Integer]] = _
acc :: [[Integer]] = _
x :: Integer = 3
[ex.hs:21:44-58] *Main> :step
]
Which I interpret as:
__lines___|__________________________________________________________________________
21:37-59 | [1] : (map ((:) 1) acc) -> [[1]
|
|
|
21:44-58 | (map ((:) 1) acc) -> does nothing, as acc = []
|
|
|
21:37-59 | [2] : (map ((:) 2) acc) -> ,
|
|
|
21:49-53 | ((:) 1) -> [1, 2]
|
|
|
21:44-58 | (map ((:) 2) acc) -> outputs nothing
|
|
|
21:37-59 | [3] : (map ((:) 3) acc) -> ,[1
|
|
|
21:49-53 | ((:) 2) -> , 2, 3]
|
|
21:44-58 | (map ((:) 3) acc) -> ]
|
Printing [[1], [1, 2], [1, 2, 3]]. Could someone explain why, when lines 49-53 are evaluated, x is the x value from the previous foldr invocation?
I know that (map ((:) x) acc) can be expanded to (foldr ((:) . ((:) x)) [] acc), as map f = foldr ((:) . f) []. So I rewrote the function into the following
prefixesSolution :: Num a => [a] -> [[a]]
prefixesSolution = foldr (\x acc -> [x] : (foldr ((:) . ((:) x)) [] acc)) []
And this works as well. Now, the lambda passed to the second foldr ((:) . ((:) x)) I would imagine could be refactored as (\ element accumulator -> (element:accumulator) . ((element:accumulator) x)). But this does not work: Couldn't match expected type ‘a -> a0 -> b0’ with actual type ‘[[a]]’. All this I have done in order to pinpoint exactly what is happening.
I also do not understand the function passed to map ((:) x).
I apologize for how convoluted this post is. At this point I don't even know what I don't know. If someone could clearly walk me through this function I would be so so grateful.
foldr accumulates from the end of the list.
Initially acc = [] (using the second argument of foldr).
Starting from the end, we apply the given function \x acc -> [x] : (map ((:) x) acc) with x = 3:
[3] : map (3 :) []
= [[3]]
With acc = [[3]], add the preceding element, x = 2:
[2] : map (2 :) [[3]]
= [[2], [2,3]]
With acc = [[2], [2,3]], add the preceding element, x = 1:
[1] : map (1 :) [[2], [2,3]]
= [[1], [1,2], [1,2,3]]
You can also still evaluate foldr "left to right", but in that case, remember that acc gets instantiated with "the next recursive call".
foldr f b (x : xs) = f x (foldr f b xs)
prefixes [1,2,3]
= [1] : map (1 :) (prefixes [2,3]) -- acc = prefixes [2,3], the next recursive call
= [1] : map (1 :) ([2] : map (2 :) (prefixes [3]))
...
Starting with the question about the function passed to map:
In Haskell, all operators are also functions. By itself, : is the list construction ("cons") operator:
1 : [2,3] -- > [1,2,3]
If you put parentheses around it, it becomes a prefix function instead of an infix operator:
(:) 1 [2,3] -- > [1,2,3]
When you remember that Haskell function application is curried, then you can see that (:) 1 is necessarily a function that prepends 1 to a list:
f = (:) 1
f [2,3] -- > [1,2,3]
So the function passed to map is one that takes a list as its argument and prepends x (the current item from the foldr) to that list.
The surrounding function prepends [x] to the result of that map, growing the list.
Next let's talk about foldr itself. It may help to think of the list [1,2,3] as the sequence of cons calls required to create it. In tree form that looks like this:
(:)
1 (:)
2 (:)
3 []
And in Haskell you could write it like this:
(:) 1 ( (:) 2 ( (:) 3 [] ) )
Given the above, what the call foldr func init [1,2,3] does is replace the final [] with the init value and all the (:)s with the supplied func. So the final result is the same as the result of this expression, which you can think of as an expansion of the foldr version:
func 1 ( func 2 ( func 3 init ) )
That is, foldr first calls the func on 3 (which becomes x) and [] (which becomes acc). (Technically, it calls the function on 3, and the result of that call is another function that it then calls on [], but that's just how function application works in Haskell; the difference is not important to this particular discussion.) Then it calls the func on 2 and the result of the first call, and then it calls it on 1 and the result of the second call.
As we established above, the func first does a map ((:) 3) [] - returning [], since mapping anything across the empty list just returns the empty list - and prepends [3] to the result, giving [[3]].
Then it calls the func on 2 and [[3]]. The map returns [[2,3]], to which it prepends [2], yielding [[2],[2,3]].
Finally it calls the func on 1 and [[2],[2,3]]. The map returns [[1,2],[1,2,3]] and the func prepends [1] to it, yielding the final answer [[1],[1,2],[1,2,3]].
When evaluating something like prefixes [1,2,3] by hand, you should try to be very careful in writing out each step of the evaluation.
I would look at it like this:
Before we start, I suggest a couple of steps of preparation. I'll also give variables fresh names as we go, to hopefully make things more clear.
It will help to write the pattern matches as case expressions, so we will do this next.
We can observe that foldr can be written as
foldr f z list =
case list of
[] -> z
(y:ys) -> f y (foldr f z ys)
I'll skip over some of the details of specific map applications later on and focus more on the foldr steps. If this is unclear, I can expand on that more.
Now that we've got that taken care of, we can evaluate. I'm not going to focus so much on the evaluation order, since this will not affect the final result. This will let me simplify a couple of things. As a result, you shouldn't necessarily assume this is exactly what the computer is doing (even though the result is the same here, it could have differences in terms of memory efficiency, time efficiency and possibly strictness properties).
prefixes [1,2,3]
==> {definition of prefixes}
foldr (\x acc -> [x] : (map ((:) x) acc)) [] [1,2,3]
==> {definition of foldr}
let f = \x acc -> [x] : (map ((:) x) acc)
in
case [1,2,3] of
[] -> []
(y:ys) -> f y (foldr f [] ys)
==> {reduce case match on known value}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (foldr f [] [2,3])
==> {definition of foldr}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (case [2,3] of
[] -> []
(y:ys) -> f y (foldr f [] ys))
==> {reduce case match on known value}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (f 2 (foldr f [] [3]))
==> {definition of foldr}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (f 2 (case [3] of
[] -> []
(y:ys) -> f y (foldr f [] ys)))
==> {reduce case match on known value}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (f 2 (f 3 (foldr f [] [])))
==> {definition of foldr}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (f 2 (f 3 (case [] of
[] -> []
(y:ys) -> f y (foldr f [] ys))))
==> {reduce case match on known value}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (f 2 (f 3 []))
==> {apply f}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (f 2 ([3] : map ((:) 3) []))
==> {apply map}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (f 2 ([3] : []))
==> {list sugar}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 (f 2 [[3]])
==> {apply f}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 ([2] : map ((:) 2) [[3]])
==> {apply map}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 ([2] : [((:) 2) [3]])
==> {list sugar}
let f = \x acc -> [x] : (map ((:) x) acc)
in
f 1 [[2], [2,3]]
==> {apply f}
[1] : map ((:) 1) [[2], [2,3]]
==> {apply map}
[1] : [((:) 1) [2], ((:) 1) [2,3]]
==> {list sugar}
[1] : [[1,2], [1,2,3]]
==> {list sugar}
[[1], [1,2], [1,2,3]]
This is the general process can be used to understand the result obtained from evaluating expressions. Note that every step is a valid Haskell expression that behaves identically to the original expression. Essentially, I just expanded definitions, reduced case expressions when the case is matching on a (:) ... ... or a [], applied functions (using beta-reduction) and introduced some syntactic sugar for lists to make things a bit easier to read in parts. Those kinds of steps already cover a significant portion of the tools you need to reduce most Haskell expressions by hand.
A very similar process can also be used for equational reasoning, which can be used as a systematic technique to optimize Haskell programs. It works by replacing expressions with other expressions that always give the same result but could have different efficiency characteristics. Essentially anything written by Richard Bird will provide examples of equational reasoning, among others.

Group Sum to N: working with list of lists

I'm learning Haskell and working on a problem where you take in a number, n, and list, iL. With these you check what consecutive numbers would be < than n and store it in a list. You can have more than one list. I've created a function called groupSumtoN that would return this list of lists.
I've created a helper function helperToSum to recursively create the list and return the output, which takes the number n, input , and acc ( the result).
Here is what I have tried so far:
groupSumtoN :: (Ord a, Num a) => a -> [a] -> [[a]]
groupSumtoN n [] = []
groupSumtoN n iL = (helperToSum n iL [])
helperToSum n [] acc = acc
helperToSum n (x:xs) acc | (sum acc) + x < n = (helperToSum n xs (acc : x))
| (sum acc) + x > n = acc:(helperToSum n xs [x])
I get two infinite type errors, one for calling helperToSum from groupSumtoN and another in this line.
(sum acc) + x < n = (helperToSum n xs (acc : x))
As an example I have an example how this function should work below:
groupSumtoN 15 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[[1,2,3,4,5],[6,7],[8],[9],[10]]
Any help would be greatly appreciated.
The base case:
helperToSum n [] acc = acc
Does not make much sense, since it expects a list of lists. You need to return a singleton list:
helperToSun n [] acc = [acc]
Another problem is that (acc : x) is not valid. (:) is a constructor of a list, and has type (:) :: a -> [a] -> [a]. You can not use it to append values. We could, for now, use (x : acc). In that case, you will later need to reverse.
It is furthermore better to use otherwise as second guard. Here for example it is possible that the sum is exactly n, and that case is not covered right now.
With these problems in mind, we can fix the compilation errors, with the following function:
helperToSum :: (Ord a, Num a) => a -> [a] -> [a] -> [[a]]
helperToSum n [] acc = [acc]
helperToSum n (x:xs) acc | (sum acc) + x <= n = (helperToSum n xs (x : acc))
| otherwise = acc:(helperToSum n xs [x])
But here the groups will be reversed, and furthermore it is not very efficient. We can make a more lazy variant that on the fly calculates how much space is left in a group, and aims to assign the items in the current, or the next group based on that condition:
groupSumtoN :: (Ord a, Num a) => a -> [a] -> [[a]]
groupSumtoN n = go n
where go _ [] = [[]]
go r (x:xs) | x <= r = let (t:tl) = go (r-x) xs in (x:t) : tl
| x > n = error "Item too large"
| otherwise = [] : go n (x:xs)
Here an empty lists, will produce a single group:
Prelude> groupSumtoN 15 []
[[]]
I leave it as an exercise to further improve this.

Rewriting list comprehension in Coq

I have the following Haskell function that outputs all possible ways to split a list:
split :: [a] -> [([a], [a])]
split [] = [([], [])]
split (c:cs) = ([], c : cs) : [(c : s1, s2) | (s1, s2) <- split cs]
Some example inputs:
*Main> split [1]
[([],[1]),([1],[])]
*Main> split [1,2]
[([],[1,2]),([1],[2]),([1,2],[])]
*Main> split [1,2,3]
[([],[1,2,3]),([1],[2,3]),([1,2],[3]),([1,2,3],[])]
I'm trying to write the same function in Coq, given there's no pattern matching by default and I don't want to define a notation for it yet, so I've decided to write a recursive function instead:
Require Import Coq.Lists.List.
Import ListNotations.
Fixpoint split {X : Type} (l : list X) : list (list X * list X) :=
match l with
| [] => [([], [])]
| c::cs =>
let fix split' c cs :=
match cs with
| [] => []
| s1::s2 => (c++[s1], s2) :: split' (c++[s1]) s2
end
in
([], c :: cs) :: ([c], cs) :: split' [c] cs
end.
which produces the same results:
= [([], [1]); ([1], [])]
: list (list nat * list nat)
= [([], [1; 2]); ([1], [2]); ([1; 2], [])]
: list (list nat * list nat)
= [([], [1; 2; 3]); ([1], [2; 3]); ([1; 2], [3]); ([1; 2; 3], [])]
: list (list nat * list nat)
However it's too verbose, any hints on how to convert this to a more readable function using HOFs in Coq?
the comprehension in the Haskell version is syntactic sugar for map (or more generally flat_map).
Fixpoint split {X : Type} (l : list X) : list (list X * list X) :=
match l with
| [] => [([], [])]
| c::cs =>
([], c :: cs) :: map (fun '(s1, s2) => (c :: s1, s2)) (split cs)
end.

Implement takeWhile with fold

How can I implement the takeWhile function in Haskell using fold?
takeWhile :: (a -> Bool) -> [a] -> [a]
I tried a strategy similiar to implementing filter like this
filter :: (a -> Bool) -> [a] -> [a]
filter f = foldr (\x acc -> if f x then x : acc else acc) []
But how can I stop when f x is false?
Just change acc to [] in the else branch:
takeWhile f = foldr (\x acc -> if f x then x : acc else []) []
The idea is that you’re lazily building the result list as you consume elements from the input list, so you return [] when you want to terminate the result list.
takeWhile (< 3) [0..]
=
0 : takeWhile (< 3) [1..]
=
0 : 1 : takeWhile (< 3) [2..]
=
0 : 1 : 2 : takeWhile (< 3) [3..]
=
0 : 1 : 2 : []
=
[0, 1, 2]
This also illustrates how Haskell lists are really streams of values. Right folds are little state machines that move step-by-step through an input stream to generate an output stream.

writing the prefix function (Haskell)

I'm writing a prefix function that will take a binary function and a list of numbers as parameters, and returns a list formed by computing the successive function and accumulating as you go.
To make things simple, Here's an example:
prefix (+) [2, 4, 1, 1]
returns [2, 6, 7, 8]
prefix (+) [0, 2, -3, 4, -5]
returns [0, 2, -1, 3, -2]
prefix max [2, 3, 1, 1]
returns [2, 3, 3, 3]
Here's my code so far however I get an error when i try to load the file because 'list is not in range'. How can i rewrite it so it makes sense to the compiler? Any help will be appreciated.
prefix' :: (a -> b) -> [a] ->[b]
prefix' _ [] = []
prefix' f (x:xs)
| ((list !! x) == 0) = f (list !! 0) (list !! 0)
| otherwise = prefix' f xs
Try this
prefix::(a -> a -> a) -> [a] -> [a]
prefix f lst| null lst = []
| null (tail lst) = lst
| otherwise = h : prefix' f (f h) (tail lst) where
h = head lst
prefix' fn fc (x:xs) | null xs = [acc]
| otherwise = acc : prefix' fn (fn acc) xs where
acc = fc x
I will try to explain the above code as much as possible. The type signature of the function is one that takes a function (a->a->a) and a list [a] as parameter and returns another list with that function applied to each adjacent pair of the list. The a in the parameter list simply implies any type (which can be anything). If we had specified a specific type (i.e. in Title case), the function will only work with that specific type
The function works by first checking if the list it recieved is empty (null lst), if so we simply return an empty list
The next thing it checks for is if the list only contains one item in it (null (tail lst)), in that case, we simply return the list
The third case is when we actually do something, and the first thing we do is to append the first element in the list to head of our new list (head lst) and call another function which we have defined on the fly to do compute the rest of the list (: prefix' f (f (head lst)) (tail lst)). Note the : separates the head from the rest of the list
The prefix' function has a type signature of (a -> a -> a) -> (a -> a) -> [a] -> [a] so as you can see the only thing different about it is that it takes one extra parameter which is a function (fc) that takes an element of type a and returns an element of type a. To create this function, we have simply passed one parameter to the initial function recieved as argument which creates this new function. This will be useful in computing the rest of the list
The base case for this new function is that if the list only contains one element, it applies the new parameter function fc to that element in the list and returns a list containing the return value of the function
Otherwise it will apply fc to the first element of the list and we generate fc again by applying fn to the return value of fc x.
If you are interested in learning how all these work, this is the website I've been using and my knowledge of haskell has improved greatly due to this website, so highly recommended
Isn't what you want to implement the scanl1 function? I'm a beginner too, but from what I understood, it goes like this:
scanl1 :: (a -> a -> a) -> [a] -> [a]
scanl1 f (x:xs) = scanl f x xs
scanl1 _ [] = []
The scanl function. which scanl1 uses, goes like this:
scanl :: (b -> a -> b) -> b -> [a] -> [b]
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)
Here's what hackage has to say about scanl:
scanl :: (b -> a -> b) -> b -> [a] -> [b] Source
scanl is similar to foldl, but returns a list of successive reduced values from the left:
scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
Note that
last (scanl f z xs) == foldl f z xs.
So, I guess the flow of execution goes like this:
scanl1 (+) [2, 4, 1, 1]
scanl (+) 2 [4, 1, 1]
scanlGo (+) 2 [4, 1, 1]
2 : scanlGo (+) (+ 2 4) [1, 1]
2 : 6 : scanlGo (+) (+ 6 1] [1]
2 : 6 : 7 : scanlGo (+) (+ 7 1) []
2 : 6 : 7 : 8 : scanlGo []
2 : 6 : 7 : 8 : []
[2, 6, 7, 8]
The same thing happens with the (*) and the max functions that you mentioned. Hope this helps.

Resources