Here is my code:
findY mnozP a =
if null(Set.toList $ mnozP)==False
then (
if (((null(intersect ( Set.toList $ head $ Set.toList $ mnozP) (a))==False) && (null(( Set.toList $ head $ Set.toList $ mnozP) \\ (a))==False)))
then (((intersect ( Set.toList $ head $ Set.toList $ mnozP) (a)) ++ (( Set.toList $ head $ Set.toList $ mnozP) \\ (a))) ++ findY ( Set.fromList $ tail $ Set.toList $ mnozP) (a))
else findY ( Set.fromList $ tail $ Set.toList $ mnozP) (a)
)
else []
findY _ a = []
findY _ _ = []
This function checks whether is list mnozP empty, if it isn't, it takes first item and checks whether its intersection with list a is empty and its difference is not empty. In case condition is true, realizes these two operations and call it recursively again for the tail of list b.
I actually got 2 questions:
Let's assume following lists: a = ["3","4"] and mnozP = [["1","6"],["2","4","3","5"]]. The output is ["3","4","2","5"]. Is there any function which can split this list into list of lists according to every single iterations? Expected output should look like [["3","4"],["2","5"]].
While compiling GHCi says following:
Warning:
Pattern match(es) are overlapped
In an equation for `findY':
findY _ a = ...
findY _ _ = ...
I'm not sure what's wrong with my patterns. I try to cover all the possible cases which can happen. Any ideas whats wrong?
EDIT: (short summary:) The function findY should return a list of lists. Every inner list is related to one concrete iteration of recursion (in case conditions is true).
The function you're looking for is the list constructor. In your inductive case, you have
(((intersect ( Set.toList $ head $ Set.toList $ mnozP) (a)) ++ (( Set.toList $ head $ Set.toList $ mnozP) \\ (a))) ++ findY ( Set.fromList $ tail $ Set.toList $ mnozP) (a))
which is just
as ++ bs ++ cs
where cs is the result of the recursive call. If findY returns a list of lists, so must the whole expression. By the induction hypothesis, cs is a list of lists. In other words, the expression to the left in exp ++ cs (i.e. as ++ bs) must be a list of lists too. But it's not! intersect and \\ return flat lists, which you concatenate together, getting a new flat list.
To fix that problem you just need to wrap your left expression in a list
[as ++ bs] ++ cs
or use the list constructor
(as ++ bs) : cs
If there's anything else you could get from this, it is that you could have found that out by yourself had the code been written in a more idiomatic way. I'll try to walk you through how I "unpacked" your code.
First, I added a type signature that matched your description.
findY :: Eq a => [[a]] -> [a] -> [[a]]
Interestingly, this change alone would have pointed out the expression in the inductive case was not right.
Then, I got rid of the Set <-> [] conversions. You can either ask for your input to be sets, or just plain lists and make sure there are no duplicates. I went with the latter approach:
findY :: Eq a => [[a]] -> [a] -> [[a]]
findY mnozP a =
if null(mnozP)==False
then (
if (((null(intersect (head mnozP) (a))==False) && (null(( head mnozP) \\ (a))==False)))
then (((intersect ( head mnozP) (a)) ++ (( head mnozP) \\ (a))) ++ findY ( tail mnozP) (a))
else findY ( tail mnozP) (a)
)
else []
findY _ a = []
findY _ _ = []
It's already getting clearer. There's loads of () you can get rid of too. In Haskell, function application is just the space character. So instead of writing f(x), like you would in many languages, you write f x and surround with parentheses only to disambiguate expressions:
findY :: Eq a => [[a]] -> [a] -> [[a]]
findY mnozP a =
if (null mnozP) == False
then
if (null (intersect (head mnozP) a) == False) && (null (head mnozP \\ a) == False)
then (intersect (head mnozP) a) ++ (head mnozP \\ a) ++ findY (tail mnozP) a
else findY (tail mnozP) a
else []
findY _ a = []
findY _ _ = []
Next, notice the many repetitions of head and tail. You could bind these to variables with a let expression, but there's a better way. Haskell allows you to pattern match on the arguments in order to choose what branch should be evaluated depending on the input. Here, we only need to know if the list has a head and a tail, which happens to be exactly how you pattern match a non-empty list:
findY :: Eq a => [[a]] -> [a] -> [[a]]
findY (xs : xss) a =
if (null (intersect xs a) == False) && (null (xs \\ a) == False)
then (intersect xs a) ++ (xs \\ a) ++ findY xss a
else findY xss a
findY _ _ = []
See how doing this allowed me to get rid of the first if statement? (I also removed the extra pattern match). There is still some redundancy, let's get rid of it:
findY :: Eq a => [[a]] -> [a] -> [[a]]
findY (xs : xss) a =
let as = intersect xs a
bs = xs \\ a
in
if (null as == False) && (null bs == False)
then as ++ bs ++ findY xss a
else findY xss a
findY _ _ = []
At that point, the issue stands out.
findY :: Eq a => [[a]] -> [a] -> [[a]]
findY (xs : xss) a =
let as = intersect xs a
bs = xs \\ a
in
if (null as == False) && (null bs == False)
then (as ++ bs) : findY xss a
else findY xss a
findY _ _ = []
Now it is a matter of style, but I personally find using pattern matching is more elegant than if statements most of the time. Not so much here though:
findY :: Eq a => [[a]] -> [a] -> [[a]]
findY (xs : xss) a =
let as = intersect xs a
bs = xs \\ a
in case (as, bs) of
((_ : _), (_ : _)) -> (as ++ bs) : findY xss a
_ -> findY xss a
findY _ _ = []
but in Haskell 2010, you can use pattern guards, a more powerful version of pattern matching. It makes your code that much clearer:
findY :: Eq a => [[a]] -> [a] -> [[a]]
findY (xs : xss) a
| as#(_ : _) <- intersect xs a
, bs#(_ : _) <- xs \\ a = (as ++ bs) : findY xss a
| otherwise = findY xss a
findY _ _ = []
Finally, the shape of your program is classic structural recursion. It is usually what you would use foldr for.
findY :: Eq a => [a] -> [[a]] -> [[a]]
findY a = foldr build []
where
build xs yss
| as#(_ : _) <- intersect xs a
, bs#(_ : _) <- xs \\ a = (as ++ bs) : yss
| otherwise = yss
Related
As a programming exercise I'm trying to build a function in Haskell where given a list it splits the list whenever an element is repeated. [1,2,3,3,4,5] would split into [[1,2,3],[3,4,5]] for example. My first idea was to split the list into a list of lists with single elements, where [1,2,3,3,4,5] would become [[1],[2],[3],[3],[4],[5]] and then merge lists only when the elements being compared are not equal, but implementing this has been a headache for me as I'm very new to Haskell and recursion has always given me trouble. I think something is wrong with the function I'm using to combine the lists, it will only ever return a list where all the elements that were broken apart are combined, where [1,2,3,3,4,5] becomes [[1],[2],[3],[3],[4],[5]] but my split_help function will transform this into [[1,2,3,3,4,5]] instead of [[1,2,3],[3,4,5]]
I've pasted my incomplete code below, it doesn't work right now but it should give the general idea of what I'm trying to accomplish. Any feedback on general Haskell code etiquette would also be welcome.
split_breaker breaks the list into a list of list and split_help is what I'm trying to use to combine unequal elements.
split_help x y
| x /= y = x ++ y
| otherwise = []
split_breaker :: Eq a => [a] -> [[a]]
split_breaker [] = []
split_breaker [x] = [[x]]
split_breaker (x:xs) = [x]:split_breaker xs
split_at_duplicate :: Eq a => [a] -> [[a]]
split_at_duplicate [x] = [[x]]
split_at_duplicate (x:xs) = foldl1 (split_help) (split_breaker [xs])
Do you want to work it something like this?
splitAtDup [1,2,3,3,3,4,4,5,5,5,5,6]
[[1,2,3],[3],[3,4],[4,5],[5],[5],[5,6]]
Am I right?
Then do it simple:
splitAtDup :: Eq a => [a] -> [[a]]
splitAtDup (x : y : xs) | x == y = [x] : splitAtDup (y : xs)
splitAtDup (x : xs) =
case splitAtDup xs of
x' : xs' -> (x : x') : xs'
_ -> [[x]]
splitAtDup [] = []
Here's a maximally lazy approach:
splitWhen :: (a -> a -> Bool) -> [a] -> [[a]]
splitWhen f = foldr go [[]] where
go x acc = (x:xs):xss where
xs:xss = case acc of
(z:_):_ | f x z -> []:acc
_ -> acc
splitAtDup :: Eq a => [a] -> [[a]]
splitAtDup = splitWhen (==)
To verify the laziness, try this:
take 2 $ take 4 <$> splitAtDup (1:2:3:3:4:5:6:undefined)
It can be fully evaluated to normal form as [[1,2,3],[3,4,5,6]].
I'm trying to write a function with the type declaration [(Int, Bool)] -> [[Int]]. I want the function to only add Ints to the same nested sublist if the Boolean is True. However if the Boolean is False, I want the Int associated with the next True bool to be added to a new sublist. For example: An input of
[(1,True),(2,True),(3,False),(4,True),(5,False),(6,False),(7,True)]
should return
[[1,2],[4],[7]].
My code so far:
test:: [(Int, Bool)] -> [[Int]]
test xs = case xs of
[]->[]
x:xs
| snd x == True -> [(fst x)] : test xs
| snd x == False -> test xs
I'm currently having issues on adding concurrent Ints to the same list if their bools are both True.
You can break this problem into two sub-problems.
For any given list, take the head of this list and match it against the rest of list. There are two possibilities during this matching: i) You are successful i.e. you match, and if so, you collect the matched value and continue looking for more values, or ii) You fail, i.e. you don't match, and if so, you stop immediately and return the so far matched result with rest of, not-inspected, list.
collectF :: (Eq a) => (a -> Bool) -> [a] -> ([a], [a])
collectF f [] = ([], [])
collectF f (x : xs)
| f x = let (ys, zs) = collectF f xs in (x : ys, zs)
| otherwise = ([], x : xs)
Now that you have the collectF function, you can use it recursively on input list. In each call, you would get a successful list with rest of, not-inspected, list. Apply collectF again on rest of list until it is exhausted.
groupBy :: (Eq a) => (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy f (x : xs) =
let (ys, zs) = collectF (f x) xs in
(x : ys) : groupBy f zs
*Main> groupBy (\x y -> snd x == snd y) [(1,True),(2,True),(3,False),(4,True),(5,False),(6,False),(7,True)]
[[(1,True),(2,True)],[(3,False)],[(4,True)],[(5,False),(6,False)],[(7,True)]]
I am leaving it to you to remove the True and False values from List. Also, have a look at List library of Haskell [1]. Hope, I am clear enough, but let me know if you have any other question.
[1] http://hackage.haskell.org/package/base-4.12.0.0/docs/src/Data.OldList.html#groupBy
Repeatedly, drop the Falses, grab the Trues. With view patterns:
{-# LANGUAGE ViewPatterns #-}
test :: [(a, Bool)] -> [[a]]
test (span snd . dropWhile (not . snd) -> (a,b))
| null a = []
| otherwise = map fst a : test b
Works with infinite lists as well, inasmuch as possible.
Here's how I'd write this:
import Data.List.NonEmpty (NonEmpty(..), (<|))
import qualified Data.List.NonEmpty as NE
test :: [(Int, Bool)] -> [[Int]]
test = NE.filter (not . null) . foldr go ([]:|[])
where
go :: (Int, Bool) -> NonEmpty [Int] -> NonEmpty [Int]
go (n, True) ~(h:|t) = (n:h):|t
go (n, False) l = []<|l
Or with Will Ness's suggestion:
import Data.List.NonEmpty (NonEmpty(..))
test :: [(Int, Bool)] -> [[Int]]
test = removeHeadIfEmpty . foldr prependOrStartNewList ([]:|[])
where
prependOrStartNewList :: (Int, Bool) -> NonEmpty [Int] -> NonEmpty [Int]
prependOrStartNewList (n, True) ~(h:|t) = (n:h):|t
prependOrStartNewList (n, False) l = []:|removeHeadIfEmpty l
removeHeadIfEmpty :: NonEmpty [Int] -> [[Int]]
removeHeadIfEmpty (h:|t) = if null h then t else h:t
This is for an assignment in Haskell.
We have been tasked with defining various functions using the foldr function.
We have been given a type:
group :: Eq a => [a] -> [[a]]
and been asked to define it such that:
group [1,2,2,3,4,4,4,5] = [[1], [2,2], [3], [4,4,4], [5]]
group [1,2,2,3,4,4,4,5,1,1,1] = [[1], [2,2], [3], [4,4,4], [5], [1,1,1]]
This is what I have so far:
group = foldr (\x xs -> if x == head (head xs) then (x : head xs) : xs else (x : []) : (head xs) : xs )
But when I try to load this into ghci interpreter I get the following error message:
Couldn't match type `[a0] -> [a]' with `[[a]]'
Expected type: [a] -> [[a]]
Actual type: [a] -> [a0] -> [a]
In the return type of a call of `foldr'
Probable cause: `foldr' is applied to too few arguments
In the expression:
foldr
(\ x xs
-> if x == head (head xs) then
(x : head xs) : xs
else
(x : []) : (head xs) : xs)
In an equation for `group':
group
= foldr
(\ x xs
-> if x == head (head xs) then
(x : head xs) : xs
else
(x : []) : (head xs) : xs)
If anyone could explain any reasons why my code isn't working as I expect it to, that would be greatly appreciated.
Thanks.
I think you are on the right track so I'll try to write your idea a bit nicer. What I want to say is this: you should pull out the first argument of foldr into an function and do pattern-matching again:
group :: Eq a => [a] -> [[a]]
group = foldr f undefined
where f x [] = undefined
f x (ys#(y:_):yss)
| x == y = undefined
| otherwise = undefined
this should do - now you only have to put in the right stuff where I put undefined :)
I'll come back later and finish it
well I guess you gave up or something - anyway here is one solution:
group :: Eq a => [a] -> [[a]]
group = foldr f []
where f x [] = [[x]]
f x (ys#(y:_):yss)
| x == y = (x:ys):yss
| otherwise = [x]:ys:yss
and a few examples:
λ> group []
[]
λ> group [1]
[[1]]
λ> group [1,1]
[[1,1]]
λ> group [1,2,1]
[[1],[2],[1]]
λ> group [1,2,2,3,4,4,4,5]
[[1],[2,2],[3],[4,4,4],[5]]
note that fs patterns are not exhaustive (which is no problem - think about why) - of course you can extent it if you want (and if you don't agree with group [] = [] than you have to.
Just to mention that if I am not wrong, this is the problem 9 from the 99 haskell problems that can be found here: https://wiki.haskell.org/99_questions/
For every problem, it has a bunch of solutions(usually) and since Carsten presented a great solution, you can go there and see other solutions so you can get different ideas on how the same thing can be achieved in various ways!
I need to compare if all elements of a given list are unique.
(For the record I am doing so for academic purposes.)
Here is what I have thus far:
allDifferent :: (Eq a) => [a] -> Bool
allDifferent list = case list of
[] -> True
(x:xs) -> if x `elem` xs then False else allDifferent xs
Which works wonderfully!
Now, when I try to do it like this...
allDifferent2 :: (Eq a) => [a] -> Bool
allDifferent2 list
| null list = True
| (head list) `elem` (tail list) || allDifferent2 (tail list) = False
| otherwise
It just doesn't work as intended.
I get the following output from GHCi:
*Main> allDifferent2 [1..4]
False
*Main> allDifferent2 [1..5]
True
*Main> allDifferent2 [1..6]
False
*Main> allDifferent2 [1..7]
True
i.e. For every list with an even amount of elements it outputs False and for an odd amount of elements, True.
What am I missing?
Would anyone care to shine some light?
An alternative exploiting notElem:
allDifferent :: (Eq a) => [a] -> Bool
allDifferent list = case list of
[] -> True
(x:xs) -> x `notElem` xs && allDifferent xs
Minor variant, using pattern matching directly in the equations:
allDifferent :: (Eq a) => [a] -> Bool
allDifferent [] = True
allDifferent (x:xs) = x `notElem` xs && allDifferent xs
I tend to stay away from partial functions like head,tail, so the variants based on guards look worse to me.
I would do this differently. Recursion + elem is O(n²). Alternatively you can first sort the list, and then compare elements pairwise. This way the sorting is O(n⋅log n), and the traversal O(n). So overall O(n⋅log n):
import Data.List
allDifferent :: (Ord a, Eq a) => [a] -> Bool
allDifferent = comparePairwise.sort
comparePairwise :: Eq a => [a] -> Bool
comparePairwise [] = True
comparePairwise [_] = True
comparePairwise (x:y:xs)
| x == y = False
| otherwise = comparePairwise (y : xs)
You can rely on library functions: allDifferent xs = nub xs == xs.
Or, written in point-free notation: allDifferent = uncurry (==) . (nub &&& id).
Using Data.Discrimination.nub, this happens in O(n) time.
The simplest reasonable idiomatic approach I can think of is
allDifferent :: Ord a => [a] -> Bool
allDifferent = pairwiseDifferent . sort
pairwiseDifferent :: Eq a => [a] -> Bool
pairwiseDifferent xs = and $ zipWith (/=) xs (drop 1 xs)
For fun with folds,
import Data.Maybe
pairwiseDifferent xs = foldr go (const True) xs Nothing
where
go x k Nothing = k (Just x)
go x k (Just prev) = x /= prev && k (Just x)
Another option is to use a Set (some of the strictness annotations may not actually be necessary):
import qualified Data.Set as S
allDifferent xs = foldr go (\s -> s `seq` True) xs S.empty
where
go x k s
| S.member x s = False
| otherwise = k $! S.insert x s
Try this:
allDifferent2::(Eq a) => [a] -> Bool
allDifferent2 list
| list == [] = True
| (head list) `elem` (tail list) = False
| otherwise = allDifferent2(tail list)
If the list is [] you should return True (As #bheklilr said :) )
If the list isn't null, you can verify if the first element is in the tail of the list. If it is, return False. Okay.
But when you say "if it is in the tail of the list OR allDifferent2 (tail list)" you are killing your function. "If all the elements are different in this list, return FALSE", and that isn't what you want.
EDIT: Yeah, it will #Luis. I fixed that by putting that "otherwise" there. When I put the guard before the allDifferent2(tail list) it checked if this function returned True. Thus it would work for [1, 1, 2] (my test-case) but not for [1, 2, 2] (similar to your case).
Sort the list, group runs of equal elements together, and check if all groups have exactly one element.
import Data.List (group, sort)
pairwiseDistinct :: Ord a => [a] -> Bool
pairwiseDistinct xs = all (\ys -> null (tail ys)) (group (sort xs))
Point-free version:
pairwiseDistinct = all (null . tail) . group . sort
This assumes that for any two elements x and y, x == y if and only if compare x y == EQ.
tail is fine here because none of the groups will ever be empty, but you can substitute drop 1 if you're averse to partial functions.
allDifferent [] = True
allDifferent (h:t) =
let (e,(l,r)) = segment h t
in e && allDifferent l && allDifferent r
segment p [] = (True,([],[])))
segment p (h:s)
| p > h = let (e,(l,r)) = segment p s in (e,(l,h:r))
| p < h = let (e,(l,r)) = segment p s in (e,(h:l,r))
| otherwise = (False,([],[])))
As you can see the structure of this solution is very similar to quickSort.
It shares as an intermediate data structure a binary tree and for that reason, the time complexity is extremely similar.
I'm trying to write a function that deletes the second occurrence of an element in a list.
Currently, I've written a function that removes the first element:
removeFirst _ [] = []
removeFirst a (x:xs) | a == x = xs
| otherwise = x : removeFirst a xs
as a starting point. However,I'm not sure this function can be accomplished with list comprehension. Is there a way to implement this using map?
EDIT: Now I have added a removeSecond function which calls the first
deleteSecond :: Eq a => a -> [a] -> [a]
deleteSecond _ [] = []
deleteSecond a (x:xs) | x==a = removeFirst a xs
| otherwise = x:removeSecond a xs
However now the list that is returned removes the first AND second occurrence of an element.
Well, assuming you've got removeFirst - how about searching for the first occurence, and then using removeFirst on the remaining list?
removeSecond :: Eq a => a -> [a] -> [a]
removeSecond _ [] = []
removeSecond a (x:xs) | x==a = x:removeFirst a xs
| otherwise = x:removeSecond a xs
You could also implement this as a fold.
removeNth :: Eq a => Int -> a -> [a] -> [a]
removeNth n a = concatMap snd . scanl go (0,[])
where go (m,_) b | a /= b = (m, [b])
| n /= m = (m+1, [b])
| otherwise = (m+1, [])
and in action:
λ removeNth 0 1 [1,2,3,1]
[2,3,1]
λ removeNth 1 1 [1,2,3,1]
[1,2,3]
I used scanl rather than foldl or foldr so it could both pass state left-to-right and work on infinite lists:
λ take 11 . removeNth 3 'a' $ cycle "abc"
"abcabcabcbc"
Here is an instinctive implementation using functions provided by List:
import List (elemIndices);
removeSecond x xs = case elemIndices x xs of
(_:i:_) -> (take i xs) ++ (drop (i+1) xs)
_ -> xs
removeNth n x xs = let indies = elemIndices x xs
in if length indies < n
then xs
else let idx = indies !! (n-1)
in (take idx xs) ++ (drop (idx+1) xs)
Note: This one cannot handle infinite list, and its performance may not be good for very large list.