Lambda expression parse error on ")" - haskell

My task is to re-implement this function
divn :: Integer -> [Integer] -> [Integer]
divn _ [] = []
divn n (x:xs) | mod x n == 0 = x : divn n xs
| otherwise = divn n xs
using 'foldr'.
What I did:
divn' _ [] = []
divn' n (x:xs) = foldr (\x -> if (mod x n == 0) (x:) ([]++)) [] xs
I thought this would work. Actually it doesn't even compile, but says: "Parse error on input ")".
As I didn't find any errors, I decided to re-write if as if' an now its working...
if' True x _ = x
if' False _ x = x
divn' _ [] = []
divn' n (x:xs) = foldr (\x -> if' (mod x n == 0) (x:) ([]++)) [] xs
Does anyone know where's the error?
Thanks!

if needs a then and an else in Haskell,
(\x -> if (mod x n == 0) (x:) ([]++))
should be
(\x -> if (mod x n == 0) then (x:) else id)

Apart from what Daniel Fischer said, you don't need any separate cases: there's no recursion, the empty list case will be handled by foldr. In your code, the first x is always ignored! Correct is
divn' n xs = foldr (\x -> if x`mod`n == 0 then (x:) else id) [] xs
or, by η-reduction,
divn' n = foldr (\x -> if x`mod`n == 0 then (x:) else id) []
Of course, it would be far more idiomatic to simply do
divn'' n = filter ((==0) . (`mod`n))

Related

Is there a way to use "<=" for pattern matching in Haskell?

I have the following code, that drops every nth element in a list.
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys 0 = []
f ys 1 = []
f [] m = []
f (y:ys) n = y : (f ys (n-1))
I would like to make it a bit shorter and was wondering if there is a way to use "<=" in pattern matching. I tried doing this using a where clause, which did not work, why?
f ys m = []
where
m <= 1 || ys == []
How can I shirk this redundancy? Is there a nice way to use "less or equal" in pattern matching?
EDIT: I tried this using guards
where
f ys m
| m <= 1 || null ys = []
| otherwise = (head ys) : (f (tail ys) (n-1))
You can work with a guard:
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys i | i <= 1 = []
f [] _ = []
f (y:ys) n = y : (f ys (n-1))
If the condition in the guard is satisfied, then that clause "fires" and thus in this case will return an empty list [].
You will however get stuck in an infinite loop, since you write f xs n ++ dropEvery (n xs) n but drop 3 [] will return [], and thus it will keep calling dropEvery with an empty list.
You can make use of recursion where we each time decrement n until it reaches 0, and then we make two hops, so:
dropEvery :: Int -> [a] -> [a]
dropEvery n = go (n-1)
where go _ [] = []
go i (x:xs)
| i <= 0 = go (n-1) xs
| otherwise = x : go (i-1) xs
We can also work with splitAt :: [a] -> ([a], [a]) and with a pattern guard:
dropEvery n [] = []
dropEvery n ds
| (_:ys) <- sb = sa ++ dropEvery n ys
| otherwise = sa
where (sa, sb) = splitAt (n-1) ds

Write haskell function using foldr

I have the following function and should write it with foldr.
f [] = []
f (x:xs)
| x == 0 = case f xs of
[] -> []
ys#(y:_) -> if y == 0 then ys else x : ys
| otherwise = x : f xs
This function basically removes all trailing 0's, but keeps at most one leading 0.
For example:
f [1,2,0,0] = [1,2]
f [1,2,0,1] = [1,2,0,1]
f [0,0,1,0,0,3] = [0,1,0,3]
I have foldr op z lst, but don't know what op can be. z should be [].
Example I traced:
foldr op [] [0,0,1,0,0,3]
-> 0 op (0 op (1 op (0 op (0 op (3 op []))))
|-- [3] ---|
|---[0,3] ------|
|-----[0,3]-----------|
|-----[1,0,3]---------------|
|-----[0,1,0,3]-------------------|
|-----[0,1,0,3]-------------------------|
How about
f = fst . foldr (\ x (xs', y) -> if y && x == 0 then (xs', x==0) else (x:xs', x==0 )) ([], True)
in this case, op returns a tuple of list and Bool, Bool is for tracking whether the accumulated list started with 0. At the end, we use fst to discard the Bool. We have to use ([], True) as the initial value, to handle the trailing zero case.

How to split a list of numbers into a set of list with all the numbers in Haskell

How do i split a list in Haskell, for example, "222 33244" into ["222","33","2","444"] only through recursion and fuctions on the prelude?
My current attempt is:
list xs
|length xs == 0 = ""
|otherwise = listSplit xs
listSplit (x:xs)
|x == head xs = x : ListSplitNext x xs
|otherwise = x:[]
listSplitNext a (x:xs)
|a == x = a : listSplitNext x xs
|otherwise = listSplit xs
So since I don't quite understand your approach and ghci lists 18 compile errors in your code, I'm afraid I can't help you with your attempt at a solution.
As pointed out in a comment, a possible solution would be:
listSplit xs = listSplit' [] (filter (`elem` ['0'..'9']) xs)
listSplit' ws (x:xs) = listSplit' (ws ++ [x : takeWhile (==x) xs]) (dropWhile (==x) xs)
listSplit' ws [] = ws
Filter every element of the string that is not a number (Data.Char.isNumber would do this, too, but the premise was to only use Prelude functions) and call listSplit' on the filtered list.
(ws ++ [x : takeWhile (==x) xs]) collects everything in xs until it reaches a letter that does not equal x, wraps this in a list and appends it to ws.
(dropWhile (==x) xs) removes every letter in xs until it reaches a letter that does not equal x.
Finally, the function calls itself with the updated ws and the reduced xs
If there are no more remaining elements, the function returns ws
If your goal is to use very few pre-defined functions this might give you some ideas:
listSplit :: String -> [String]
listSplit xs =
let (as, a) = foldr go ([], []) numbers
in a : as
where
isNumber x = x `elem` ['0'..'9']
numbers = filter isNumber xs
go cur (res, []) = (res, [cur])
go cur (res, lst#(a:_))
| a == cur = (res, a : lst)
| otherwise = (lst : res, [cur])
Of course you can replace foldr with your own recursion as well:
numberSplit :: String -> [String]
numberSplit xs =
let numbers = filter (`elem` ['0'..'9']) xs
in listSplit numbers
listSplit :: Eq a => [a] -> [[a]]
listSplit =
reverse . go [] []
where
go acc as [] = as : acc
go acc [] (x:xs) = go acc [x] xs
go acc as#(a:_) (x:xs)
| a == x = go acc (a : as) xs
| otherwise = go (as : acc) [x] xs
I had a moment to implement this but I think this is what you're looking for.
listSplit s = go filtered
where filtered = [c | c <- s, elem c ['0'..'9']]
go [] = []
go (x:xs) = (x : takeWhile (== x) xs) : (go $ dropWhile (== x) xs)

How to report an error in Haskell code

I am writing a program that returns every rth element from a list. The list can be any type. I want to report an error when r is zero but my code isn't working (it is working fine when I comment out the error line). Can anyone tell me how to report an error in this situation
rthElem :: Int -> [a] -> [a]
rthElem _ [] = []
rthElem 0 (x:xs) = "Error"
rthElem n (x:xs) = rthElem' n 1 (x:xs) where
rthElem' n i (x:xs) = (if (n `divides` i) then
[x] else
[])
++ (rthElem' n (i+1) xs)
rthElem' _ _ [] = []
divides x y = y `mod` x == 0
You could use Maybe or Either in this case.
This is how Maybe looks. Nothing will be our "error".
rthElem :: Int -> [a] -> Maybe [a]
rthElem _ [] = Just []
rthElem 0 (x:xs) = Nothing
rthElem n (x:xs) = Just (rthElem' n 1 (x:xs)) where
rthElem' n i (x:xs) = (if (n `divides` i) then
[x] else
[])
++ (rthElem' n (i+1) xs)
rthElem' _ _ [] = []
divides x y = y `mod` x == 0
main :: IO ()
main = case (rthElem 0 [1..5]) of
Nothing -> putStrLn "Error"
Just elm -> print elm
Another way is using Either. Either will return Left or Right. Left will be our "error".
rthElem :: Int -> [a] -> Either String [a]
rthElem _ [] = Right []
rthElem 0 (x:xs) = Left "Error"
rthElem n (x:xs) = Right (rthElem' n 1 (x:xs)) where
rthElem' n i (x:xs) = (if (n `divides` i) then
[x] else
[])
++ (rthElem' n (i+1) xs)
rthElem' _ _ [] = []
divides x y = y `mod` x == 0
main :: IO ()
main = case (rthElem 0 [1..5]) of
Left err -> putStrLn err
Right elm -> print elm
The best way is using Either. Read more about error handling here.
If you really want to print an error and show it you could use the error function, error :: String -> a
rthElem 0 (x:xs) = error "Error msg here"
But there is a plenty better ways to do this , and you should figure out which one fits in your case , you can use Maybe, Either even monads , here is an interesting link with examples http://www.randomhacks.net/2007/03/10/haskell-8-ways-to-report-errors/
You could use exceptions but you'd also have to transform your function into an IO action.
rthElem :: Int -> [a] -> IO [a]
rthElem _ [] = return []
rthElem 0 _ = ioError $ userError "Error"
rthElem n l = return $ rthElem' n 1 l where
rthElem' n i (x:xs) = (if (n `divides` i) then
[x] else
[])
++ (rthElem' n (i+1) xs)
rthElem' _ _ [] = []
divides x y = y `mod` x == 0

Drop nth Element from list

I have been teaching myself Haskell for a month or so and today I was reading the solution of 16th problem and came up with a question.
Here is a link : http://www.haskell.org/haskellwiki/99_questions/Solutions/16
Basically, this question asks to make a function that drops every N'th element from a list.
For example,
*Main> dropEvery "abcdefghik" 3
"abdeghk"
The first solution in the link is
dropEvery :: [a] -> Int -> [a]
dropEvery [] _ = []
dropEvery (x:xs) n = dropEvery' (x:xs) n 1
where
dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1))
dropEvery' [] _ _ = []
divides x y = y `mod` x == 0
My question is why dropEvery defines the case of empty lists while dropEvery' can take care of empty list?
I think dropEvery [] _ = [] can be simply eliminated and modifying a bit of other sentences as following should work exactly the same as above and looks shorter.
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = dropEvery' xs n 1
where
dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1))
dropEvery' [] _ _ = []
divides x y = y `mod` x == 0
Can anyone help me figure out about this?
I think they are the same and the author could have simplified the code as you suggested. For the heck of it I tried both versions with QuickCheck and they seem to be the same.
import Test.QuickCheck
dropEvery :: [a] -> Int -> [a]
dropEvery [] _ = []
dropEvery (x:xs) n = dropEvery' (x:xs) n 1
where
dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1))
dropEvery' [] _ _ = []
divides x y = y `mod` x == 0
dropEvery2 :: [a] -> Int -> [a]
dropEvery2 xs n = dropEvery' xs n 1
where
dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1))
dropEvery' [] _ _ = []
divides x y = y `mod` x == 0
theyAreSame xs n = (dropEvery xs n) == (dropEvery2 xs n)
propTheyAreSame xs n = n > 0 ==> theyAreSame xs n
And in ghci you can do
*Main> quickCheck propTheyAreSame
+++ OK, passed 100 tests.
I also tested a few corner cases by hand
*Main> dropEvery [] 0
[]
*Main> dropEvery2 [] 0
[]
*Main> dropEvery [] undefined
[]
*Main> dropEvery2 [] undefined
[]
So them seem to the same.
So our learning outcomes:
Quickcheck is perfect for this kind of stuff
Don't underestimate yourself. :)

Resources