How can we limit recursive calls in Haskell? - 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)

Related

Symmetric Relation in Haskell

I'm working with relations and I want to find whether a relation is symmetric.
To find that a relation is symmetric, we need to find two tuples such that: [(a,b), (b,a)].
This is what I've got so far:
simmetry:: Eq a => [(a,a)] -> [a]
simmetry [] = []
simmetry (x:xs)
| (fst x `elem` map snd xs) && (snd x `elem` map fst xs) = fst x : (simmetry xs)
| otherwise = simmetry xs
What this function does is, it grabs a tuple x and checks that it finds its first element in another tuple as the second position, as well as checking that the second element is in another tuple as the first position.
However I'm missing out on the part where I have to check that the other tuple is the same one for both conditions. With my code, something like this: [(a,b),(b,c),(d,a)] would work.
P.D: simmetry returns [a] for testing purposes.
I'm out of ideas, any tips are highly appreciated!
What you want to check is: for every tuple (x,y) in the list, (y,x) should also be present. You can express that quite directly in Haskell:
isSymmetric :: Eq a => [(a,a)] -> Bool
isSymmetric l = all (\(x,y) -> (y,x)`elem`l) l
This is actually doing some redundant work because it always also goes over (x,y) itself, which your not really interested in, but it doesn't really matter. However it's a good exercise to design this in a way so it doesn't go over the element itself; for this it's helpful to use an auxiliary function
foci :: [a] -> [(a,[a])]
witht the behaviour
foci [p,q,r] ≡ [(p,[q,r]), (q,[p,r]), (r,[p,q])]
Then you left with an all over the foci of the input list, i.e.
isSymmetric = all _ . foci
With what #Rik Van Toor said:
simmetry:: Eq a => [(a,a)] -> [a]
simmetry [] = []
simmetry (x:xs)
| (snd x, fst x) `elem` xs = fst x : (simmetry xs)
| otherwise = simmetry xs

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"

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) ]

Splitting list into sublists in 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 ==

Haskell split a list into two by a pivot value

I want to split [a] into ([a], [a]) by a pivot value and I have my code
splitList :: (Ord a) => a -> [a] -> ([a],[a])
splitList pivot list =
([x | x <- list, x <= pivot], [x | x <- list, x > pivot])
But it iterates the list twice to generate two lists, is there a way to iterate only once?
There are two possibilities, depending on if you want a tail recursive solution (and don't care about reversing the order of elements), or a solution that consumes its argument lazily.
The lazy solution decides if the first element of the list goes into the first or into the second part and uses a simple recursion to process the rest of the list. This would be the preferred solution in most cases as laziness is usually more important than tail recursion:
splitList :: (Ord a) => a -> [a] -> ([a],[a])
splitList _ [] = ([], [])
splitList p (x : xs)
| x <= p = (x : l, r)
| otherwise = (l, x : r)
where
~(l, r) = splitList p xs
However in some cases you care neither for the ordering of elements nor for laziness, but instead for speed. (For example when implementing a sorting algorithm.) Then a variant that uses an accumulator to build the result (see Accumulating Parameters: Getting rid of the 'almost' in "almost tail recursive" ) to achieve tail recursion would be more appropriate:
splitListR :: (Ord a) => a -> [a] -> ([a],[a])
splitListR pivot = sl ([], [])
where
sl acc [] = acc
sl (l, g) (x : xs)
| x <= pivot = sl (x : l, g) xs
| otherwise = sl (l, x : g) xs
It's generally considered good style to avoid hand-rolling your recursion; instead you can use a folding function like so:
splitList pivot = foldr triage ([],[])
where
triage x ~(lows, highs)
| x <= pivot = (x:lows, highs)
| otherwise = (lows, x:highs)
Of course it's even better style to make use of a preexisting function that does exactly what you need, i.e. partition. :)
If you want to write this from scratch, you can maintain two lists, one for small items, one for large. First I'll write the wrapper:
splitList :: (Ord a) => a -> [a] -> ([a],[a])
splitList pivot input = spL input [] [] where
OK, so I"m just calling spL and giving it two empty lists to start off with. Because I'm using a where block, I'll not need to pass the pivot around, so only the three lists that are changing get passed. If we haven't got anything left in the input, we're done and should return the answer:
spL [] smalls larges = (smalls,larges)
Now as you'll see, we'll actually make smalls and larges backwards, so if you don't like that, replace the final answer pair there with (reverse smalls,reverse larges). Let's deal with some input now:
spL (i:input) smalls larges | i <= pivot = spL input (i:smalls) larges
| otherwise = spL input smalls (i:larges)
So we pop it on the front of the smalls if it's small enough.
The reason for pushing on the front of the list is it saves us iterating through to the end of the list every time. You can always reverse to obtain the original ordering if that matters to you, like I said.
All together we get:
splitList :: (Ord a) => a -> [a] -> ([a],[a])
splitList pivot input = spL input [] [] where
spL [] smalls larges = (smalls,larges)
spL (i:input) smalls larges | i <= pivot = spL input (i:smalls) larges
| otherwise = spL input smalls (i:larges)
import Data.List (partition)
splitList pivot = partition (<= pivot)
http://www.cs.indiana.edu/pub/techreports/TR27.pdf of 19761 suggests the following:
import Control.Applicative
partition3 [] p = ZipList [[], [], []]
partition3 (x:xs) p
| x < p = ZipList [(x:),id,id] <*> partition3 xs p
| x > p = ZipList [id,id,(x:)] <*> partition3 xs p
| True = ZipList [id,(x:),id] <*> partition3 xs p
using it, we write
splitList pivot list = (a++b, c)
where
[a,b,c] = getZipList $ partition3 list pivot
1 as seen here.

Resources