Idiomatic Haskell way of termination recursion in this functoin - haskell

What is the more haskellish way to stop the recursion of this function? Currently I'm using a nested if/else, and returning an empty list if the next combination "overflows".
nextcomb [] [] = []
nextcomb lst maxes | length lst == length maxes =
let lastel = last lst
in if lastel < last maxes
then (init lst) ++ [lastel+1]
else let higherbit = (nextcomb (init lst) (init maxes))
in if higherbit == []
then []
else higherbit ++ [1]
nextcomb lst maxes | otherwise = []
To clarify, what it does is it takes a list of numbers like [1,1,1,1] and increments it like:
[1,1,1,1] -> [1,1,1,2]
...
[1,1,1,9] -> [1,1,2,1]
...
[1,1,9,9] -> [1,2,1,1]
etc.
BUT, the second argument is a list that indicates the maxmum value for each column. So if the maxes were [2,3], and the initial list was [1,1], then the progression woudld be:
[1,1] -> [1,2]
[1,2] -> [1,3]
[1,3] -> [2,1]
[2,1] -> [2,2]
[2,2] -> [2,3]
[2,3] -> []
Edit: "Little Endian" version as recommended by chepner
nextcomb' [] [] = []
nextcomb' lst maxes | length lst /= length maxes = []
nextcomb' lst maxes =
let firstel = head lst
in if firstel < head maxes
then (firstel+1) : (tail lst)
else let higherbit = (nextcomb' (tail lst) (tail maxes))
in if higherbit == []
then []
else 1 : higherbit

You should make illegal states unrepresentable
So, instead of using two lists, use a list of tuples. For example, the first value in each tuple could be the maximum, the second one the actual value.
This also simplifies the logic dramatically, as the errors "maxes too long" and "maxes too short" can not happen.

Your if expression is simply hiding the real base case, which is that if either argument is empty, return the empty list.
nextcomb [] [] = []
nextcomb lst maxes | length lst != length maxes = []
nextcomb lst maxes = let lastel = last lst
in if lastel < last maxes
then (init lst) ++ [lastel+1]
else let higherbit = (nextcomb (init lst) (init maxes))
in if higherbit == []
then []
else higherbit ++ [1]
I would probably rework the logic like this. (Note, I'm far from a Haskell expert and tend to answer these questions as an exercise for myself :)
-- Reversing the arguments and the ultimate return value
-- lets you work with the head of each list, rather than the last
-- element
nextcomb lst maxes = reverse $ nextcomb' (reverse lst) (reverse maxes)
-- The real work. The base case is two empty lists
nextcomb' [] [] = []
-- If one list runs out before the other, it's an error. I think
-- it's faster to check if one argument is empty when the other is not
-- than to check the length of each at each level of recursion.
nextcomb' [] _ = error "maxes too long"
nextcomb' _ [] = error "maxes too short"
-- Otherwise, it's just a matter of handling the least-significant
-- bit correctly. Either abort, increment, or reset and recurse
nextcomb' (x:xs) (m:ms) | x > m = error "digit too large"
| x < m = (x+1):xs -- just increment
| otherwise = 0:(nextcomb' xs ms) -- reset and recurse
(Actually, note that nextcomb' [] _ won't trigger if you don't recurse after the last digit. You could argue that a too-long maxes isn't a big deal. I'll leave this unfixed, as the next part handles it correctly.)
Alternately, you could verify the lengths match in the initial call; then you can assume that both will become empty at the same time.
nextcomb lst maxes | length lst == length maxes = reverse $ nextcomb' (reverse lst) (reverse maxes)
| otherwise = error "length mixmatch"
nextcomb' [] [] = []
nextcomb' (x:xs) (m:ms) | x > m = error "digit too large"
| x < m = (x+1):xs
| otherwise = 0:(nextcomb' xs ms)
Here's an example using Either to report errors. I won't vouch for the design other than to say it does type check and run. It's not too different from the previous code; it just uses <$> to lift reverse and (0:) to work with arguments of type Either String [a] instead of arguments of type [a].
import Control.Applicative
nextcombE lst maxes = reverse <$> nextcombE' (reverse lst) (reverse maxes)
nextcombE' [] [] = Right []
nextcombE' [] _ = Left "maxes too long"
nextcombE' _ [] = Left "maxes too short"
nextcombE' (x:xs) (m:ms) | x > m = Left "digit too large"
| x < m = Right ((x+1):xs)
| otherwise = (0:) <$> (nextcombE' xs ms)

Please check if next implementation is useful for you, because a more "haskellish" way (at least for me), is using built in recursive functions to achieve the same goal
nextcomb [] [] = []
nextcomb lst maxes
| length lst /= length maxes = []
| lst == maxes = []
| otherwise = fst $ foldr f ([],True) $ zip lst maxes
where
f (l,m) (acc, mustGrow)
| mustGrow && l < m = (l + 1:acc, False)
| mustGrow = (1:acc, True)
| otherwise = (l:acc, False)
(Edited) If need catch errors then can try this:
nextcomb [] _ = Left "Initial is empty"
nextcomb _ [] = Left "Maximus size are empty"
nextcomb lst maxes
| length lst /= length maxes = Left "List must be same length"
| lst == maxes = Left "Initial already reach the limit given by Maximus"
| otherwise = Right $ fst $ foldr f ([],True) $ zip lst maxes
where
f (l,m) (acc, mustGrow)
| mustGrow && l < m = (l + 1:acc, False)
| mustGrow = (1:acc, True)
| otherwise = (l:acc, False)

Let's draw a diagram! I'm going to make slightly different assumptions than the initial problem:
A little-endian representation like chepner suggested;
Instead of inclusive maximum values, I'm going to go with exclusive bases to make things more similar to addition-with-carry.
I'm going to use digits in the range [0, base).
Here's the diagram:
digits = [d0, d1, ..., dn]
bases = [b0, b1, ..., bn]
--------------------------
result = [r0, r1, ..., rn]
Now we can ask: for each digit ri of the result, what does its value depend on? Well, these things:
The value of di
The value of bi
Whether the previous r resulted in a carry
So we can write this as a function:
import Control.Monad.State -- gonna use this a bit later
type Base = Int
type Digit = Int
type Carry = Bool
-- | Increment a single digit, given all the contextual information.
singleDigit' :: Base -> Digit -> Carry -> (Digit, Carry)
singleDigit' base digit carry = (digit', carry')
where sum = digit + if carry then 1 else 0
digit' = if sum < base then sum else sum - base
carry' = base <= sum
Note that I took care to make sure that the singleDigit' function's type ends with Carry -> (Digit, Carry). This is because that fits the state -> (result, state) pattern that is typical of the state monad:
-- | Wrap the `singleDigit'` function into the state monad.
singleDigit :: Base -> Digit -> State Carry Digit
singleDigit base digit = state (singleDigit' base digit)
Now with that we can write the following function:
increment :: [Base] -> [Digit] -> [Digit]
increment bases digits = evalState (sequence steps) True
where steps :: [State Carry Digit]
steps = zipWith singleDigit bases digits
What we're doing here is:
Using zipWith to "sew" the bases and digits list together on corresponding elements. The elements of this list correspond to the individual steps of the computation.
Using sequence :: [State Carry Digit] -> State Carry [Digit] to chain all the individual steps into one big step that passes the intermediate Carry state around.
Feeding True as the initial Carry input to that big chain of steps (which causes the chain to increment).
Example invocation:
>>> take 20 (iterate (increment [3,4,5,10]) [0,0,0,0])
[[0,0,0,0],[1,0,0,0],[2,0,0,0]
,[0,1,0,0],[1,1,0,0],[2,1,0,0]
,[0,2,0,0],[1,2,0,0],[2,2,0,0]
,[0,3,0,0],[1,3,0,0],[2,3,0,0]
,[0,0,1,0],[1,0,1,0],[2,0,1,0]
,[0,1,1,0],[1,1,1,0],[2,1,1,0]
,[0,2,1,0],[1,2,1,0]
]
The lessons I'd stress:
Break problems into smaller pieces. Don't try solve too much in one function! In this case, the trick was to split off the solution for single digits into its own function.
It pays very much to think carefully about the data flow in a problem: what information is needed at each step of the problem? In this case, the diagram helped reason that out, which led to the singleDigit' function.
One of the big ideas of functional programming is to separate the "shape" of the computation from its "content". In this case, the "content" is the singleDigit operation, and the "shape" of the computation—how to combine the individual steps into a big solution—is provided by the State monad and the sequence operation.
I did not write a single recursive function; instead, I made ample use of library functions like zipWith, sequence, take and iterate. You ask for a more idiomatic Haskell solution, so well, here goes: complicated recursive functions definitions are not as idiomatic as using library functions that encapsulate common recursive patterns.
This hopefully will encourage you to study monads some more. There are many, many problems out there where, if you express them in terms of one of the standard monads like State, you can reuse generic functions like sequence to solve them very easily. It's a tall learning curve but the results are worth it!

Related

Clean syntax for conditionally folding a list in Haskell

I'm relatively new to haskell, but in my searching I couldn't find an easy way to conditionally fold a list. i.e. When an element satisfies a condition (like in filter) to fold that element by a function (like foldr and foldl).
My workaround was to write the following helper function, then apply map to change the resulting list of pairs as my situation required.
-- This function returns tuples containing the elements which
-- satisfy `cond` folded right, adding 1 to the second value
-- in each pair. (`snd` pair starts at 0)
-- Condition takes a single value (similar to `filter`)
-- NOTE: list cannot end with token
foldrOn cond list =
if (length list) > 0 then
if cond (head list) then
do
let tmp = foldrOn cond (tail list)
(fst (head tmp), snd (head tmp) + 1) : (tail tmp)
-- fold token into char after it
else
(head list, 0) : (foldrOn cond (tail list))
-- don't fold token
else
[] -- base case len list = 0
foldlOn cond list = ...
For example, the use-case would be something along the lines of wanting to remove the zeros in the following lists but remember how many were removed between each value.
-- the second value in each resultant pair represents the number of
-- zeroes preceding the corresponding first value in the original list.
foldrOn (== 0) [1,0,0,0,0,0,1,0,0,0,1] -- [(1,0),(1,5),(1,3)]
foldrOn (== 0) [1,0,0,12,0,13] -- [(1,0),(12,2),(13,1)]
Is there a better way to accomplish this?
Additionally, can this be done more optimally?
First of all,
foldrOn :: Num t => (a -> Bool) -> [a] -> [(a, t)]
-- foldrOn (== 0) [1,0,0,0,0,0,1,0,0,0,1] -- [(1,0),(1,5),(1,3)]
foldrOn p xs = foldr g [] xs
where
g x [] = [(x,0)]
g x ((y,n):r)
| p x = ((y,n+1):r)
g x r = ((x,0):r)
This is the simplest, though it is recursive, i.e. will force the whole list to the end before starting returning its result.
To make it maximally lazy we'd have to use a lazy left fold. The skipping over the p-satisfying elements is still a recursive step, but at least the process will pause between each such span.
Lazy left fold is usually implemented as a foldr with additional argument being passed left to right along the list:
foldlOn :: Num t => (a -> Bool) -> [a] -> [(a, t)]
-- foldlOn (== 0) [1,0,0,0,0,0,1,0,0,0,1] -- [(1,0),(1,5),(1,3)]
foldlOn p xs = foldr g z xs 0
where
g x r i | p x = r (i+1)
| otherwise = (x,i) : r 0
z _i = []
Or you could combine span/break and unfoldr to do the same.
You might find a way to use groupBy with some post-processing step:
GHCi> groupBy (\a b -> (==0) b) [1,0,0,0,0,0,1,0,0,0,1]
[[1,0,0,0,0,0],[1,0,0,0],[1]]
GHCi> groupBy (const (==0)) [1,2,0,0,1,0,1]
[[1],[2,0,0],[1,0],[1]]
Finishing this should not be a problem.
You can always bring some builtin machinery. The Data.List library is quite powerful:
import Data.List(mapAccumL)
import Data.Maybe(catMaybes)
foldrOn cond = catMaybes . snd . mapAccumL combine 0 where
combine a el =
if cond el then (a + 1, Nothing)
else (0, Just (el, a))
What's going on
Essentially, foldrOn cond is a composition of the following functions:
mapAccumL combine 0 which advances along the list modifying each element by information about the number of recently skipped entities (starting the count at 0 and resetting it whenever we find something that doesn't match the cond predicate).
snd which discards the final state from the mapAccumL's result
catMaybes which removes the Maybe layer and leaves only the "present" values.
Let's start by using pattern matching to make your own implementation more idiomatic, more obviously correct, and also (much) faster. We can also use guards in an idiomatic fashion rather than if/then/else; this is rather less important. There's also no reason to use do here, so we won't.
foldrOn _cond [] = []
foldrOn cond (hd : tl)
| cond hd
= case foldrOn cond tl of
(x, y) : tl' -> (x, y + 1) : tl'
-- fold token into char after it
[] -> error "String ended on token."
| otherwise
= (hd, 0) : foldrOn cond tl
-- don't fold token
This is ... okay. But as Will Ness suggests, we don't actually gain anything by consing an "incomplete" element onto the result list. We can instead count up the cond-satisfying tokens until we reach the end of the block, and then produce a complete element. I think this makes the code a little easier to understand, and it should also run a little bit faster.
foldrOn cond = go 0
where
go count (hd : tl)
| cond hd
= go (count + 1) tl -- Don't produce anything; just bump the count
| otherwise
= (hd, count) : go 0 tl -- Produce the element and the count; reset the count to 0
go count []
| count == 0
= []
| otherwise
= error "List ended on a token."
To actually run faster, you might need to tell the compiler explicitly that you really want to calculate the counts. You probably don't need to understand this part just yet, but it looks like this:
-- At the top of the file, add this line:
{-# LANGUAGE BangPatterns #-}
foldrOn cond = go 0
where
go !count (hd : tl)
| cond hd
= go (count + 1) tl -- Don't produce anything; just bump the count
| otherwise
= (hd, count) : go 0 tl -- Produce the element and the count; reset the count to 0
go count []
| count == 0
= []
| otherwise
= error "List ended on a token."
This can be written as a fold in the manner Will Ness demonstrates.
Note: while it's possible to avoid the BangPatterns language extension, doing so is a bit annoying.

How to shorten a Haskell implementation like this?

I have a function with a lot of guards that look like this:
function
| p `elem` [0,1,2,3,4,5,6] = [0,1,2,3,4,5,6]
| p `elem` [7,8,9,10,11,12,13] = [7,8,9,10,11,12,13]
| p `elem` [14,15,16,17,18,19,20] = [14,15,16,17,18,19,20]
| otherwise = []
I'm sure I can write this much shorter with Haskell. If not, then it's okay. I'm new to Haskell and I would love to become better at it by learning different approaches.
Perhaps using "map" may be a good start? But then, I'm not sure how to pass in those specific lists.
The values are not always contiguous.
What about simple bounds checks?
function p
| p < 0 = []
| p < 7 = [0..6]
| p < 14 = [7..13]
| p < 21 = [14..20]
| otherwise = []
It will be faster and for some applications use less memory.
If you don't want to perform a bounds check (but an element check), you can still use the shortened list notation.
Alternatively, you could construct a helper function that iterates over the lists:
helper (x:xs) p | elem p x = x
| otherwise = helper xs p
helper [] _ = []
function = helper [[0..6],[7..13],[14..20]]
Although this is actually longer, you can easily extend the function to use other lists. Note however that this function will be slower, since elem requires O(n) time whereas a bounds check takes O(1) time.
You can also - as is suggested in #jamshidh's answer construct a Data.Map which is a datastructure that guarantees O(log n) lookup time:
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe(fromMaybe)
helper2 :: Ord a => [[a]] -> a -> [a]
helper2 lst p = fromMaybe [] $ Map.lookup p (Map.fromList $ concatMap (\x -> zip x (repeat x)) lst)
function = helper2 [[0..6],[7..13],[14..20]]
For this last piece, it generates (\x -> zip x (repeat x)) generates for a list tuples containing an element of the list e and the entire list l. For example:
Prelude> (\x -> zip x (repeat x)) [0..6]
[(0,[0,1,2,3,4,5,6]),(1,[0,1,2,3,4,5,6]),(2,[0,1,2,3,4,5,6]),(3,[0,1,2,3,4,5,6]),(4,[0,1,2,3,4,5,6]),(5,[0,1,2,3,4,5,6]),(6,[0,1,2,3,4,5,6])]
This works as follows: x unifies with a list, for instance [0,1,2,3,4,5,6], now we apply a zip function on [0,1,2,3,4,5,6] and on the infinite list [[0,1,2,3,4,5,6],[0,1,2,3,4,5,6],[0,1,2,3,4,5,6],....]. zip generates tuples as long as both lists feed elements, so it takes the first element from [0,1,..,6] and the first from [[0,1,..,6],[0,1,..,6],[0,1,..,6],...] so the resulting tuple is (0,[0..6]), next it takes the second element 1 from the list, and the second item from the repeat function, thus (1,[0..6]). It keeps doing this -- although lazily -- until one of the lists is exhausted which is the case for the first list.
You can use the list monad here.
func p = join $ do x <- [[1,3,5], [2,4,6], [7,8,9]]
guard $ p `elem` x
return x
The list of lists are the things you want to check against. The call to guard filters out the choices that don't succeed. As long as the candidate lists are disjoint, at most one will succeed. return x evaluates to either [] or [x] for one of the choices of x, so join
reduces [x] to [].
> func 1
[1,3,5]
> func 2
[2,4,6]
> func 7
[7,8,9]
> func 10
[]
As a list comprehension, it would look like
func p = join [x | x <-[[1,3,5],[2,4,6],[7,8,9]], p `elem` x]
First create the list of lists
lists = [[0,1,2,3,4,5,6], [7,8,9,10,11,12,13], [14,15,16,17,18,19,20]]
Then create a mapping from value to list
theMap = concat $ map (\x -> zip x (repeat x)) lists
This will give you what you need
> lookup 1
Just [0,1,2,3,4,5,6]
Note that the output is a Maybe, in the case you don't supply a value in any list.

Foldr Application

Recently I am trying to solve a problem using Foldr. The task is following:
In:[5,1,3,8,2,4,7,1]
Out:[16,8]
It means, I will double those element of the input list which is in the odd index position and even digit. I wrote the program without using foldr which is following:(It shows pattern match failure: head[])
findPos list elt =
map fst $ filter ((elt==).snd) $ zip [0..] list
doublePos [] = []
doublePos (x:xs)
| ((head(findPos xs x)`mod` 2) /= 0) && (x `mod` 2 == 0) =
[2*x] ++ doublePos xs
| otherwise = doublePos xs
How do I write this program using foldr?
foldr isn't really a good choice for this function, as you need to pass the parity of the index of each element from the front of the list.
A list comprehension is probably the cleanest:
doublePos xs = [2*x | (i,x) <- zip [0..] xs, even x, odd i]
or you could use plain old recursion:
doublePos' (_:x:xs)
| even x = (2*x) : doublePos' xs
| otherwise = doublePos' xs
doublePos' _ = []
Though, if you must use foldr, you can do it by having the accumulator be a function
which takes the parity of the current index as an argument:
doublePos'' xs = foldr step (const []) xs False where
step x next p
| p && even x = 2*x : next (not p)
| otherwise = next (not p)
Why your existing code gives you a pattern match failure: doublePos [5,1,3,8,2,4,7,1] matches the second equation with x = 5 and xs = [1,3,8,2,4,7,1]. This causes head (findPos [1,3,8,2,4,7,1] 5) to be evaluated, but that reduces to head [] and you get your error.
To expand on this: what you seem to be hoping to get out of findPos is the index of the current element, relative to the start of the original list. But what you actually get out of it is the index of the next occurrence of the current element, relative to the next element... and if it doesn't occur again, you get an error.
(Using characters as list elements here to avoid confusion between list indices and list elements.)
0 1 2 3 4 5 6 7 8 9 10 <-- indices relative to start
'H':'e':'l':'l':'o':' ':'t':'h':'e':'r':'e':[] <-- original list
| |
x = 'e' | V say we're here
xs = 'l':'l':'o':' ':'t':'h':'e':'r':'e':[] head (findPos xs x) = 6 but we wanted 1
| ^
x = 'o' say we're here instead
xs = ' ':'t':'h':'e':'r':'e':[] head (findPos xs x) = error "head []" but we wanted 4
The only way this can possibly work is if you pass the original list to findPos. But the only list you have available is that part of the original list you have not yet recursed into. Anyway, there are better ways of doing this, as seen in hammar's answer.

Haskell Hamming numbers, works but shows duplicates

I am trying to generate hamming numbers in haskell, the problem is I get duplicate #'s in my output list and I cannot figure out why exactly. Should I just create a remove duplicates function or am I just missing something simple?
Also in the function hamming I would like to make sure the size of the input list is exactly 3, how do I find the size of a list so I can do the comparison?
{- Merge lists x&y of possibly infinite lengths -}
merge [] [] = []
merge [] ys = ys
merge xs [] = xs
merge xs ys = min x y : if x < y then merge (tail xs) ys
else merge xs (tail ys)
where x = head xs
y = head ys
{- multiply each element in y by x -}
times x [] = []
times x y = x * (head y) : times x (tail y)
{- find the hamming numbers of the input primes list -}
ham [] = []
ham x = 1 : merge (times (head x) (ham x))
(merge (times (x !! 1) (ham x)) (times (last x) (ham x)))
{- returns x hamming #'s based on y primes of size 3 -}
hamming x [] = []
hamming x y = take x (ham y)
{- hamming x y = if "y.size = 3" then take x (ham y)
else "Must supply 3 primes in input list" -}
You get duplicates because many of the hamming numbers are multiples of several of the base numbers, and you don't remove duplicates in your merge function. For example, for the classical 2, 3, 5 Hamming numbers, you obtain 6 as 2 * 3 as well as 3 * 2.
You could of course create a duplicate removal function. Since the list you create is sorted, that wouldn't even be very inefficient. Or you could remove the duplicates in the merge function.
how do I find the size of a list so I can do the comparison?
You can obtain the length of a list using the length function that is available from the Prelude, but let me warn you right now that calling length should only be done if the length is really required, since length has to traverse the entire list to calculate its length. If the list happens to be long, that takes a lot of time, and may cause huge memory usage if the list is referenced elsewhere so that it cannot be garbage-collected. If the list is even infinite, evaluating its length will of course never terminate.
What you want to do can also be achieved by pattern-matching,
ham [a, b, c] = list
where
list = 1 : merge (map (a*) list) (merge (map (b*) list) (map (c*) list))
ham _ = []
You could also use a guard with a length check
hamming x y
| length y == 3 = take x (ham y)
| otherwise = []
to make sure that your input list has exactly three elements, but you will regret that if you call hamming 10 [1 .. ].
In the List module, Haskell has a duplicate remover called nub. Here it is on hoogle: http://www.haskell.org/hoogle/?hoogle=nub. This is O(n^2) though, so you might be better off changing merge. But it may be worthwhile to first use a slow solution already written for you, before optimizing.
I suspect that you are trying to learn Haskell with this little exercise, but here's another way to write out the hamming numbers (no duplicates, but not in order) using the List monad:
uglyNumbers = do { n <- [0..]
; k <- [0..n]
; j <- [0..n-k]
; return $ (2^(n-k-j))*(3^j)*(5^k) }
This makes a lazy, infinite list of hamming numbers. You can equivalently write this using a list comprehension:
uglyNumbers' = [(2^(n-k-j))*(3^j)*(5^k) | n <- [0..], k <- [0..n], j <- [0..n-k]]

How to remove an element from a list in Haskell?

The function I'm trying to write should remove the element at the given index from the given list of any type.
Here is what I have already done:
delAtIdx :: [x] -> Int -> [x]
delAtIdx x y = let g = take y x
in let h = reverse x
in let b = take (((length x) - y) - 1) h
in let j = g ++ (reverse b)
in j
Is this correct? Could anyone suggest another approach?
It's much simpler to define it in terms of splitAt, which splits a list before a given index. Then, you just need to remove the first element from the second part and glue them back together.
reverse and concatenation are things to avoid if you can in haskell. It looks like it would work to me, but I am not entirely sure about that.
However, to answer the "real" question: Yes there is another (easier) way. Basically, you should look in the same direction as you always do when working in haskell: recursion. See if you can make a recursive version of this function.
Super easy(I think):
removeIndex [] 0 = error "Cannot remove from empty array"
removeIndex xs n = fst notGlued ++ snd notGlued
where notGlued = (take (n-1) xs, drop n xs)
I'm a total Haskell noob, so if this is wrong, please explain why.
I figured this out by reading the definition of splitAt. According to Hoogle, "It is equivalent to (take n xs, drop n xs)". This made me think that if we just didn't take one extra number, then it would be basically removed if we rejoined it.
Here is the article I referenced Hoogle link
Here's a test of it running:
*Main> removeIndex [0..10] 4
[0,1,2,4,5,6,7,8,9,10]
deleteAt :: Int -> [a] -> [a]
deleteAt 0 (x:xs) = xs
deleteAt n (x:xs) | n >= 0 = x : (deleteAt (n-1) xs)
deleteAt _ _ = error "index out of range"
Here is my solution:
removeAt xs n | null xs = []
removeAt (x:xs) n | n == 0 = removeAt xs (n-1)
| otherwise = x : removeAt xs (n-1)
remove_temp num l i | elem num (take i l) == True = i
| otherwise = remove_temp num l (i+1)
remove num l = (take (index-1) l) ++ (drop index l)
where index = remove_temp num l 1
Call 'remove' function with a number and a list as parameters. And you'll get a list without that number as output.
In the above code, remove_temp function returns the index at which the number is present in the list. Then remove function takes out the list before the number and after the number using inbuilt 'take' and 'drop' function of the prelude. And finally, concatenation of these two lists is done which gives a list without the input number.

Resources