Rewriting list comprehension in Coq - list-comprehension

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.

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.

How to get a list of tuples and create a list of tuples with lists inside of them

My goal is to take an input like:
[(8, P1), (8, P2), (10, P3)]
And turn it into something like:
[(8, [P1, P2]), (10, P3)]
Given that numbers like 8 and 10 are the datatype Time (wrapping and Int) and P1 and P2 are the datatypes Person (which wraps a String). This is what I did so far:
groupTogether :: [(Time, Person)] -> [(Time, Person)]
groupTogether [] = []
groupTogether ((x, y) : (a, b) : ks)
| x == a = (x, (y : (b))) : groupTogether ks
| otherwise = (x, y) : groupTogether ((a, b) : ks)
And It "kinda" works but usually the outputs are things like (8, Name1Name2) instead of (8, [Name1, Name1]). And I just don't know how to write what the function should do once there is only one element in the list. It says that there is an "exaustive pattern" missing. What am I doing wrong? If I try to put the elements togheter using : the code won't run.
How about this? (Note that the Foldable t can be though of as a list)
% ghci
λ> :m +Data.Map
λ> data P = P1 | P2 | P3 deriving (Eq, Ord, Show)
λ> let input = [(8, P1), (8, P2), (10, P3)] :: [(Int, P)]
λ> :type Prelude.foldl
_ :: Foldable t => (b -> a -> b) -> b -> t a -> b
λ> :type Prelude.foldl (\mp (k, p) -> insertWith (<>) k [p] mp)
_ :: (Foldable t, Ord k) => Map k [a] -> t (k, a) -> Map k [a]
λ> :type Prelude.foldl (\mp (k, p) -> insertWith (<>) k [p] mp) mempty
_ :: (Foldable t, Ord k) => t (k, a) -> Map k [a]
λ> :type Prelude.foldl (\mp (k, p) -> insertWith (<>) k [p] mp) mempty input
_ :: Map Int [P]
λ> Prelude.foldl (\mp (k, p) -> insertWith (<>) k [p] mp) mempty input
fromList [(8,[P2,P1]),(10,[P3])]
λ> toList (Prelude.foldl (\mp (k, p) -> insertWith (<>) k [p] mp) mempty input)
[(8,[P2,P1]),(10,[P3])]
What about this?
import Data.List
import Data.Function
data P = P1 | P2 | P3 deriving Show
x = [(8, P1), (8, P2), (10, P3)]
fun list = let lists = groupBy ((==) `on` fst) x -- [[(8,P1),(8,P2)],[(10,P3)]]
nums = map (fst . head) lists -- [8,10]
ps = (map . map) snd lists -- [[P1,P2],[P3]]
in zip nums ps -- [(8,[P1,P2]),(10,[P3])]
In lists I've grouped the items by equality on the number, in nums I've extracted the number which is common to all items in each group, in ps I've extracted those P* things, whatever they are, via (map . map) . snd which applies snd through two functorial layers.
Note that if in general the items in x with equal number are not necessarily adjacent (in your example they are), you might want to sort the list before using groupBy, using an appropriate sorting algorithm, as suggested in the comments below.
As regards your desired output
[(8, [P1, P2]), (10, P3)]
this is simply not possible to obtain, because in Haskell all the elemnts of a list have the same type, but (8, [P1, P2]) and (10, P3) have to different types, namely (Time, [Person]) and (Time, Person). This was already implied by some of the comments under your question, but you haven't corrected your question yet (you should). In my answer I've assumed you meant to write [(8, [P1, P2]), (10, [P3])].
As regards your attempt
groupTogether :: [(Time, Person)] -> [(Time, Person)]
groupTogether [] = []
groupTogether ((x, y) : (a, b) : ks)
| x == a = (x, (y : (b))) : groupTogether ks
| otherwise = (x, y) : groupTogether ((a, b) : ks)
there are several syntactic problems with it:
the signature is wrong, as it signals that the output has the same type of the input; this is certainly possible, but does not reflect the (corrected) desired output; probably you meant to write groupTogether :: [(Time, Person)] -> [(Time, [Person])]
groupTogether [] = [] handles an empty list input, whereas groupTogether ((x, y) : (a, b) : ks) handles a two-elements-or-more list input, but there's no way to deal with a singleton list, which is exactly what the "exaustive pattern missing" error alludes to;
since y and b have the same type, Person, the expression y : (b) is incorrect because it's equivalent to y:b, and : wants an a on the left and a [a] on the right; you might want to change that to y:[b], or maybe [y,b];
in a similar way, y in the otherwise case should be [y].
However, even if you apply the corrections above, there would still be something that is not quite right. Look at this:
groupTogether ((x, y) : (a, b) : ks)
| x == a = (x, y : [b]) : groupTogether ks
You're pattern matching the first two pair in the list and putting them in one single pair, but what if the first pair in ks has another a as its first element? You're leaving it in ks, not grouping it with the other two. This is either wrong or not clear from the text of your question, in which case you should improve it.

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

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]

Is there a way to get a 'split' function in Haskell to accept two different types of input?

I am trying to create a function split that can take either [Int] and Int or [Char] Char to split either a list of integers on an integer given or split a string on a character given. I.e.
Main> split [1,2,3,0,4,5,0,0,7,8,9] 0
[[1,2,3],[4,5],[7,8,9]]
Main> split "Mary had a little lamb" ' '
["Mary","had","a","little","lamb"]
I've tried using Either and (Eq a) but it still doesn't seem to work. Below is what I've tried doing using class instances but I know very little about this and get the error Haskell 98 does not support multiple parameter classes.
The best way I think I'd understand it would be to use pattern matching or list comprehensions. Any help much appreciated.
class Split a where
split :: (Eq a) => [a] -> a -> [a]
instance Split [Char] Char where
split [] c = [""]
split (x:xs) c
| x == c = "" : (split xs c)
| otherwise = (x : head (split xs c)) : tail (split xs c)
instance Split [Int] Int where
split [] n = []
split (x:xs) n
| x == n = [] : (split xs n)
| otherwise = (x : head (split xs n)) : tail (split xs n)
I can get the split function to work with strings and characters but not lists of integers.
You need a polymorphic function split
split :: (Eq a) => [a]->a->[[a]]
Implementation is simple
split [] _ = [[]]
split (x:xs) c
| x == c = [] : (split xs c)
| otherwise = (x : head subSplit) : tail subSplit
where
subSplit = split xs c
EDIT
I suggest different implementation.
split :: Eq a => [a] -> a -> [[a]]
split x c = map reverse $ split' x c []
where
split' :: Eq a => [a] -> a -> [a] -> [[a]]
split' [] _ a = [a]
split' (x:xs) c a
| x == c = a : split' xs c []
| otherwise = split' xs c (x:a)
Just to contribute with an other approach. This solution uses foldr. I think it is quite neat but less undestable than #talex's
split :: (Eq a) => [a] -> a -> [[a]]
split l c = foldr f acc l
where acc = [[]]
f a t#(i#(x:_):xs) = if a == c then []:t else (a:i):xs -- Case when the current accumulator is not empty
-- | |- cons a to current accumulator
-- |- start a new accumulator
f a t#([]:xs) = if a == c then t else [a]:xs -- Case when the current accumulator is empty. Usefull when two separators are together
-- | |- cons a to current accumulator
-- |- Don't start a new accumulator, just continue with the current
Just correct solution.
split :: Eq a => [a] -> a -> [[a]]
split xs delim = go $ dropWhile (== delim) xs
where
go [] = []
go xs = let (tok, rest) = break (== delim) xs
in tok : go (dropWhile (== delim) rest)
Data.List.Split.splitOn (available from the split package) is close:
> splitOn [0] [1,2,3,0,4,5,0,0,7,8,9]
[[1,2,3],[4,5],[],[7,8,9]]
> splitOn " " "Mary had a little lamb"
["Mary","had","a","little","lamb"]
Your split :: Eq a => [a] -> a -> [[a]] would be
split lst d = filter (not.null) $ splitOn [d] lst

calculating number of inversions in a list in haskell

how do we get calculate inversions in a list in Haskell?
eg. [1, 2, 3, 1] , xi > xj where i < j is the condition for inversion. In the given example it would be 3.
I tried the following code:
module Inversion where
inv :: Ord a => [a] -> [(a, a)]
inv [] = []
inv xs = [(a, b) | a <- xs, b <- tail xs, a > b]
I even tried to zip it with tail and then get the pairs.
import Data.List
inv :: Ord a => [a] -> [(a, a)]
inv xs = [(a,b) | (a:bs) <- tails xs, b <- bs, a > b]
This is a naive implementation close to what you already got:
inv :: Ord a => [a] -> [(a, a)]
inv [] = []
inv xs = [(a, b) | b <- xs', a > b] ++ inv xs'
where xs' = tail xs
a = head xs
It does the first thing that comes to mind: compare the first element with every other element in the list and then do the same with the rest of the list.
Your example:
*Main> inv [1,2,3,1]
[(2,1),(3,1)]
This seems to work for me:
inv lst = filter nonOrdPair $ zip lst (tail lst)
where nonOrdPair (a,b) = a > b
on your example gives
Prelude> inv [1, 2, 3, 1]
[(3,1)]
if you only need the first element you can get it with map fst.
You can't use zip and tail in this case. This would lead to only comparing consecutive pairs where you need all pairs. So given a list (x:xs), you need to check whether any of the xs is smaller than x:
import Data.Maybe (mapMaybe)
checkInv :: Ord a => a -> a -> Maybe (a,a)
checkInv x y = if x <= y then Nothing
else Just (x, y)
inv :: Ord a => [a] -> [(a,a)]
inv [] = []
inv (x:xs) = mapMaybe (checkInv x) xs ++ inv xs
> inv [1,2,3,1]
[(2,1), (3,1)]
Just to throw some folds into the matter:
inv :: Ord a => [a] -> [(a,a)]
inv [x] = [] :: [(x,x)]
inv xs = foldl (\acc x -> if (head xs) > x then (head xs, x) : acc else acc) [] xs
Zipping and then filtering the pairs is not a bad idea, but you have to consider all the pairs for that to work:
inv xs = filter (\(a, b) -> a > b) $ allPairs xs
where
allPairs xs = allPairsHelp xs (tail xs)
where
allPairsHelp xs [] = []
allPairsHelp xs ys = zip xs ys ++ allPairsHelp xs (tail ys)

Resources