Splitting list into sublists in Haskell - haskell

How can I split a list into 2 sublists, where first sublist includes elements from begin of initial list and equals to first element, and second sublist contains others elements? I have to resolve this without using Prelude functions.
My base solution is:
partSameElems :: [a] -> ([a],[a])
partSameElems [] = ([],[])
partSameElems (x:xs) = fstList (x:xs) scdList (x:xs)
where
fstList (x:y:xs) = if x == y then x:y:fstList xs {- I need to do Nothing in else section? -}
scdList (x:xs) = x:scdList xs
For example:
[3,3,3,3,2,1,3,3,6,3] -> ([3,3,3,3], [2,1,3,3,6,3])
Now I can offer my version of solution:
partSameElems :: Eq a => [a] -> ([a],[a])
partSameElems [] = ([],[])
partSameElems (x:xs) = (fstList (x:xs), scdList (x:xs))
where
fstList [] _ = []
fstList (x:xs) el = if x == el then x:fstList xs el else []
scdList [] _ = []
scdList (x:xs) el = if x /= el then (x:xs) else scdList xs el

This is easier if you don't try to do it in two passes.
parSameElems [] = ([], [])
parSameElems lst = (reverse revxs, ys)
where (revxs, ys) = accum [] lst
accum xs [y] = ((y:xs), [])
accum xs (y1:y2:ys) | y1 == y2 = accum (y1:xs) (y2:ys)
| otherwise = ((y1:xs), (y2:ys))
Not sure you can use guard syntax in where clauses. You will also have to implement reverse yourself since you can't use Prelude, but that's easy.
Note: I haven't actually run this. Make sure you try and debug it.
Also, don't write the type signature yourself. Let ghci tell you. You got it wrong in your first try.

Another implementation can be
partition [] = ([],[])
partition xa#(x:xs) = (f,s)
where
f = takeWhile (==x) xa
s = drop (length f) xa
should be clear what it does.
> partition [3,3,3,3,2,1,3,3,6,3]
([3,3,3,3],[2,1,3,3,6,3])

I assume the "without resorting to Prelude function" means it's educational. Probably aimed at working on recursion, given it's manipulation of List data. So let's emphasize this
Recursive algorithms are simpler to express when input and output types are identical.
Let's rather say that instead of a list [3,3,3,3,2,1,3,3,6,3], your input data is composed of
the front list, but at this stage it's empty
the remainder, at this stage equals to input [3,3,3,2,1,3,3,6,3]
recursion input is then ([],[3,3,3,2,1,3,3,6,3])
The type of the central function will be ([a],[a]) -> ([a],[a])
Now, each recursion step will take the front element of the remainder and either put if in the front list or stop recursion (you reached the final state and can return the result)
module SimpleRecursion where
moveInFront :: (Eq a) => ([a],[a]) -> ([a],[a])
moveInFront (xs , [] ) = ( xs , [])
moveInFront ([] , y:ys ) = moveInFront ( y:[] , ys)
moveInFront (x:xs , y:ys ) = if x == y then moveInFront ( y:x:xs , ys)
else (x:xs, y:ys)
partSameElems :: (Eq a) => [a] -> ([a],[a])
partSameElems a = moveInFront ([],a)
What we have here is a classical recursion scheme, with
- stop condition (x /= y)
- recursion clause
- coverage of trivial cases
Notes :
- writing y:x:xs actually reverses the front list but since all values are equal the result is ok
Please don't do that kind of trick in the code of an actual program, it would come back to bite you eventually
- the function only works on lists of Equatable data (Eq a) => because the recursion / stop condition is the equality test ==

Related

How can we limit recursive calls in Haskell?

I've got a problem with my code, which is the following:
import Data.List
splitat _ [] = ([],[])
splitat element (head:tail)
| element == head = ([],(head:tail))
| otherwise = ([head]++fst(splitat element tail), snd(splitat element tail))
It splits a list at 'element', then combining the left and right sublist into a tuple.
However, in the third line, the 'splitat element tail' command is called twice, once through 'fst' and once through 'snd'. Is there a way to evaluate this term only 1 time to keep the recursion tree narrow?
Thanks in advance.
Yes. You can make use of a let expression, or a where clause. For example:
splitat :: Eq a => a -> [a] -> ([a], [a])
splitat _ [] = ([],[])
splitat x' xa#(x:xs) | x == x' = ([], xa)
| otherwise = (x:ys1, ys2)
where (ys1, ys2) = splitat x' xs
Note: please do not use head :: [a] -> a or tail :: [a] -> [a] or other functions that are defined as variables, since these will shadow the existing binding. It makes it harder to reason about the code, since a person might think that head and tail refer to these functions, and not the variables.
Use Control.Arrow.first (or Data.Bifunctor.first; the arrow library ships with GHC, while I don't recall if you need to install bifunctor first or not):
splitat _ [] = ([],[])
splitAt e lst#(h:t) | e == h = ([], lst)
| otherwise = first (h:) (splitAt e t)

How to inform GHC that a particular pattern match is impossible (ex: list will never be empty)?

I defined selectionSort function as below, sorting an empty list just results in an empty list and sorting a non-empty list is cons of minimum element and sorted version of rest of the list.
selectionSort :: Ord a => [a] -> [a]
selectionSort xs
| null xs = []
| otherwise = minElem : (selectionSort ys)
where
(minElem, ys) = minf xs
where
minf [x] = (x, [])
minf (x:xs) = let (m ,ms) = minf xs in
if x <= m then (x, xs)
else (m, x:ms)
minf takes a non-empty list and returns a tuple of minimum value and rest of the list.
When i compile this function with -W flag, I get this warning
warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for `minf': Patterns not matched: []
|
24 | minf [x] = (x, [])
| ^^^^^^^^^^^^^^^^^^...
It is straight forward that the function minf is never applied to an empty list, because those cases are caught in null xs = []. Is there any way to inform GHC that the particular case is impossible without using other types (NonEmpty list type) or Maybes
Usually the idea is to "design" types in such way that the number of "impossible patterns" is very small (and prefereably zero).
As a poor man solution, you can rewrite the signature of the function from:
foo :: [a] -> b -- [a] is a non-empty list
to:
foo :: a -> [a] -> b -- head and tail as input
So in this context we can rewrite your function to:
selectionSort :: Ord a => [a] -> [a]
selectionSort [] = []
selectionSort (x:xs) = minElem : selectionSort ys
where (minElem, ys) = minf x xs
minf z [] = (z, [])
minf z za#(z2:zs) = let (m, ms) = minf z2 zs in
if z <= m then (z, za)
else (m, z:ms)
So we here use the first parameter as the head of the list, and the second as the tail. Since the list contains at least one element, this means that the tail can be empty, and hence we can do pattern matching. As a result, we can still use the -Wincomplete-patterns flag to check if all patterns are covered and thus we still have some guarantees by the compiler.
In case you still have no means to design the types properly, you can for example add the pattern and raise a (validation) error:
minf [] = error "Impossible: minf only works with a non-empty list"

How to process / summarise a list into a "different" list

I think I need something like a fold or maybe a foldt but the examples I've seen, seem to only compress the list into a simple scalar value.
What I need would need to remember and re-use values from previous lines in the list (essentially a "group by" operation)
If my input data looks like:
[["order1", "item1"],["", "item2"],["","item3"],["order2","item4"]]
What is the correct approach to end up with something like:
[["order1",["item1","item2","item3"]],["order2",["item4"]]
ie data Order = Order { id :: Text, items :: [OrderItem]}
What if I wanted a slightly different structure?
[("order1",["item1","item2","item3"]),("order",["item4"])]
ie data OrderTuple = OrderTuple { order :: Order, items :: [OrderItem]}
What if I also wanted to keep a running total of some numeric value from the OrderItem?
edit: Here's the code I'm trying to get working based on Frerich's answer
--testGroupBy :: [[String]] -> [[String]]
testGroupBy :: [[String]] -> [(String, [String])]
testGroupBy z =
--groupBy (\(x:xs) (y:ys) -> x == y || null y) z
groupBy testFunc z
testFunc :: [String] -> [String] -> Bool
testFunc (x:xs) (y:ys) = x == y || null y
Pattern matching is useful here
groupData = foldl acc []
where acc ((r, rs):rss) ("":xs) = (r, rs ++ xs): rss
acc rss (x:xs) = (x, xs): rss
acc _ _ = error "Bad input data"
resultant groups are in reverse order, use reverse if you need.
What if I wanted a slightly different structure?
Simply transform one into other, you can do inside groupData or as separated function.
If you admit initial groups without fst element
groupData = foldr acc []
where acc (x:xs) [] = [(x, xs)]
acc ("":xs) (("", rs):rss) = ("", rs ++ xs): rss
acc (x:xs) (("", rs):rss) = (x, rs ++ xs): rss
acc (x:xs) rss = (x, xs): rss
then
let xs = [["", "item8"],["", "item9"],["order1", "item1"],["", "item2"],["","item3"],["order2","item4"]]
print $ groupData xs
is
[("",["item9","item8"])
,("order1",["item3","item2","item1"])
,("order2",["item4"])]
Instead of looking for a fold-based solution, I'd first try to see whether you can define a function as a composition of higher-level functions (such as map). Let me fire up a ghci session and play abit:
λ: let x = [["order1", "item1"],["", "item2"],["","item3"],["order2","item4"]]
Your "group by" operation actually has an existing name: Data.List.groupBy -- this almost gets us what we need:
λ: import Data.List
λ: let x' = groupBy (\(x:xs) (y:ys) -> x == y || null y) x
λ: x'
[[["order1","item1"],["","item2"],["","item3"]],[["order2","item4"]]]
This groupBy application puts all elements in x into one group (i.e. list) whose first element is equal, or if the second element is empty. This can then get massaged into your desired format (in this case, the second one you proposed with a map):
λ: let x'' = map (\x -> (head (head x), map (!! 1) x)) x'
λ: x''
[("order1",["item1","item2","item3"]),("order2",["item4"])]
Putting it all together:
groupData :: [[String]] -> [(String, [String])]
groupData = map (\x -> (head (head x), map (!! 1) x))
. groupBy (\(x:xs) (y:ys) -> x == y || y == "")
I suppose that with this, building a proper data structure (i.e. something more typesafe than nested lists) should be straightforward.

Combs on a large set doesn't compute Haskell

I'm writing a combs function in haskell
what it needs to do is, when I provide it with a deck of cards, give me every combination of hands possible from that deck of size x
This is the relevant code
combs :: Int -> [a] -> [[a]]
combs 0 _ = [[ ]]
combs i (x:xs) = (filter (isLength i) y)
where y = subs (x:xs)
combs _ _ = [ ]
isLength :: Int -> [a] -> Bool
isLength i x
| length x == i = True
| otherwise = False
subs :: [a] -> [[a]]
subs [ ] = [[ ]]
subs (x : xs) = map (x:) ys ++ ys
where ys = subs xs
However, when I ask it to compute a combs 5 [1..52], e.g. a hand of 5 out of a full deck, it does not provide a result, and keeps running for a really long time
Does anyone know what the problem is and how to speed up this algorithm?
To extract i items from x:xs you can proceed in two ways:
you keep the x, and extract only i-1 elements from xs
you discard x, and extract all the i elements from xs
Hence, a solution is:
comb :: Int -> [a] -> [[a]]
comb 0 _ = [[]] -- only the empty list has 0 elements
comb _ [] = [] -- can not extract > 0 elements from []
comb i (x:xs) = [ x:ys | ys <- comb (i-1) xs ] -- keep x case
++ comb i xs -- discard x case
By the way, the above code also "proves" a well-known recursive formula for the binomial coefficients. You might already have met this formula if you attended a calculus class.
Letting B(k,n) = length (comb k [1..n]), we have
B(k+1,n+1) == B(k,n) + B(k+1,n)
which is just a direct consequence of the last line of the code above.
Right now it's a bit hard to see what you are trying to do - but I guess the problems you have is that you gonna filter and map a lot.
I think a simple way to get what you need is this:
module Combinations where
import Data.List (delete)
combs :: Eq a => Int -> [a] -> [[a]]
combs 0 _ = [[]]
combs i xs = [ y:ys | y <- xs, ys <- combs (i-1) (delete y xs) ]
which uses delete from Data.List
It should be lazy enough to find you combinations quick - of course all will take a while ;)
λ> take 5 $ combs 5 [1..52]
[[1,2,3,4,5],[1,2,3,4,6],[1,2,3,4,7],[1,2,3,4,8],[1,2,3,4,9]]
how does it work
it's one of those recursive combinatorial algorithm that works by selecting a first card y from all the cards xs, and then recursivley gets the rest of the handysfrom the deck without the selected carddelete a xsand then putting it back togethery:ys` inside the list-monad (here using list-comprehensions).
BTW: ther are 311,875,200 such decks ;)
version without list-comprehensions
here is a version without comprehensions in case your system has issues here:
combs :: Eq a => Int -> [a] -> [[a]]
combs 0 _ = [[]]
combs i xs = do
y <- xs
ys <- combs (i-1) (delete y xs)
return $ y:ys
version that will remove permutations
this one uses Ord to get sort the items in ascending order and in doing so removing duplciates in respect to permutaion - for this to work xs is expected to be pre-sorted!
Note chi's version is working with fewer constraints and might be more preformant too - but I thougt this is nice and readable and goes well with the version before so maybe it's of interest to you.
I know it's not a thing often done in Haskell/FP where you strife for the most general and abstract cases but I come form an environment where most strive for readability and understanding (coding for the programmer not only for the compiler) - so be gentle ;)
combs' :: Ord a => Int -> [a] -> [[a]]
combs' 0 _ = [[]]
combs' i xs = [ y:ys | y <- xs, ys <- combs' (i-1) (filter (> y) xs) ]

How to return last element in the list using function in haskell?

My professor gave me an example to get last element in the list using "laste" function:
he stated that: definition in the form of “laste xs = …” is not acceptable, whereas definition in the form of “laste = …” is acceptable.
I have tried something like this: Please correct me if my solution is wrong according to problem statement.
laste :: [a] -> Maybe a
laste [] = Nothing
laste (x:[]) = Just x
laste (x:xs) = laste xs
But this gives me answer for example:
ghci>laste[1,2,3,4]
Just 4
I want to get rid of this "Just".
Is there any solution to remove Just?
You would need to change the signature of the function to return a simple element.
The thing is that you would need to return an error in case of empty list.
laste :: [a] -> a
laste [] = error "Can't handle empty lists." -- or some other error message
laste [x] = x
laste (x:xs) = laste xs
While Charmini2's answer is functionally correct, it doesn't solve the problem of retrieving the last element in pointfree form. Consider
laste :: [a] -> a
laste = foldr1 (\_ a -> a)
It works according to specs as foldr1 expects a non-empty list. Intuition for why it returns the last element in the list can be gotten from the observation that foldr1 replaces every (:) in the structure of the list with the lambda in the above equation, which basically selects the rightmost of two elements. Repeat, and you get the last.
I think your professor meant was that you need to re-implement the Prelude function last
in a point-free style.
non point-free example:
filterEven xs = filter even xs
point-free exapmle:
filterEven = filter even
point-free examples of last:
lastv1 = (head . reverse)
lastv2 = foldl1 (\acc x -> x)
lastv3 = foldr1 (\x acc -> acc)
lastv4 = \(x:xs) -> if null xs then x else lastv4 xs
lastv5 = \e -> case e of
[x] -> x
(_:xs) -> lastv5 xs
otherwise -> error "empty list"
Here a possible working solution:
last' :: [a] -> a
last' [] = error "empty"
last' (x:[]) = x
last' (x:xs) = last' xs

Resources