Convert List comprehension into recursive call - haskell

sieve [] = []
sieve (a:x) = a : sieve [y| y <- x, y `mod` a > 0]
I want to convert this code to recursive implementation or using higher order functions such as map and filter. I can't figure out how do I do this.
I have tried this way but it wont seem to work
sieve (a:x) = f x : map f xs where f = y `mod` a > 0

Is this the kind of thing you want? The list comprehension is only being used to filter the list anyway, so we can convert to a form that manually applies a filter.
sieve [] = []
sieve (x:xs) = x : sieve (filter (\y -> y `mod` x > 0) xs)

In addition to Chris' fine answer, which boils down to "understand what the code is doing and intuit the correct translation", there is a much more mechanical translation you can do. The behavior of list comprehensions is specified in the Haskell Report:
Translation: List comprehensions satisfy these identities, which may be used as a translation into the kernel:
[e | True] = [e]
[e | q] = [e | q, True]
[e | b, Q] = if b then [e | Q] else []
[e | p <- l, Q] = let ok p = [e | Q]
ok _ = []
in concatMap ok l
[e | let decls, Q] = let decls in [e | Q]
where e ranges over expressions, p over patterns, l over list-valued expressions, b over boolean expressions, decls over declaration lists, q over qualifiers, and Q over sequences of qualifiers. ok is a fresh variable. The function concatMap, and boolean value True, are defined in the Prelude.
Here's how those rules would apply to your code.
[y | y <- x, y `mod` a > 0]
= { fourth equation }
let ok y = [y | y `mod` a > 0]
ok _ = []
in concatMap ok x
= { second equation }
let ok y = [y | y `mod` a > 0, True]
ok _ = []
in concatMap ok x
= { third equation }
let ok y = if y `mod` a > 0 then [y | True] else []
ok _ = []
in concatMap ok x
= { first equation }
let ok y = if y `mod` a > 0 then [y] else []
ok _ = []
in concatMap ok x
After this process, you're left with no list comprehensions. Then we can start applying other transformations we know about; for example, the second clause of ok here seems to be dead code, so:
= { dead code elimination }
let ok y = if y `mod` a > 0 then [y] else []
in concatMap ok x
= { inlining }
concatMap (\y -> if y `mod` a > 0 then [y] else []) x
Whether you can make the intuitive leap from this version of the code to filter is of course another question entirely! But it's not necessary to make that leap: this concatMap version has no list comprehensions left at all and behaves exactly the same as the original.

Related

Haskell, how to return a list without encountering an error

So I'm trying to wrap my head around Haskell with my first project where i have a function encountering an error:
Exception: prelude.head: empty list.
selectNextGuess :: [[Card]] -> [Card]
selectNextGuess lst
| length lst >= 1250 = lst !! (div (length lst) 2)
| otherwise = newGuess
where fbList = [[feedback x y | x <- lst, y <- lst]]
valuesList = [(calcValues(group $ sort[feedback y x | y <- lst, y /= x]), x) | x <- lst]
(_, newGuess) = head(sort valuesList)
Any advice in steering me in the right direction to solve this would be greatly appreciated.
Cheers
TL;DR: since a list can be empty, and there is no minimal element in the empty list, the way to return a list without the error is to maybe return a list, or rather to return a Maybe list.
If you call selectNextGuess [], lst inside the function selectNextGuess becomes []. Then, valuesList = [(calcValues(group $ sort[feedback y x | y <- lst, y /= x]), x) | x <- [] ] = [] is also an empty list. And then (_, newGuess) = head (sort valuesList) = head (sort []) = head [] is called.
But there is no head element in the empty list. This is what the error message is telling us. You called head with [], which is forbidden, because it has no answer.
The usual solution is to make this possibility explicit in the data type. We either have just one answer, for a non-empty list, or we have nothing:
data Maybe a = Just a | Nothing
is such built-in type. So we can use it, and handle the empty lst explicitly:
selectNextGuess :: [[Card]] -> Maybe [Card]
selectNextGuess lst
| length lst >= 1250 = Just $ lst !! (div (length lst) 2)
| null lst = Nothing
| otherwise = Just newGuess
where fbList = [[feedback x y | x <- lst, y <- lst]]
valuesList = [(calcValues(group $ sort[feedback y x | y <- lst, y /= x]), x)
| x <- lst]
(_, newGuess) = head (sort valuesList)
Using null as a guard like that is a bit of an anti-pattern. We usually achieve the same goal with the explicit pattern in a separate clause, like
selectNextGuess :: [[Card]] -> Maybe [Card]
selectNextGuess [] = Nothing
selectNextGuess lst
| length lst >= 1250 = Just $ lst !! (div (length lst) 2)
| otherwise = Just newGuess
where ......
Using that head ... sort ... combination to find the minimal element is perfectly fine. Due to Haskell's lazy evaluation and the library sort being implemented as bottom-up mergesort, it will take O(n) time.
There is also a shorter way to write down the same thing,
....
| otherwise = listToMaybe . map snd $ sort valuesList -- or,
= listToMaybe [ x | (_, x) <- sort valuesList ] -- whichever you prefer.
where fbList = .....
valuesList = .....
Since there is no more than one value "inside" a Maybe _, the conversion function listToMaybe already takes just head element, implicitly.
Moreover, it produces Nothing automatically in the empty list [] case. So the explicit pattern clause can be removed, this way.

Check for an element in the rest of the list (lx)

i recently picked up Haskell and i am having trouble putting in code the way to look if an element is in the rest of the list (x:lx) in this case in lx.
My code:
atmostonce:: [Int] -> Int -> Bool
atmostonce [] y = True
atmostonce (x:lx) y
| (x==y) && (`lx` == y) = False
| otherwise = True
The way it is now checks for the first element (x==y) but i don't know how to check if the element y exists in lx. The thing i am actually trying to accomplish is to find out if in the list of Intigers lx the number y contains 0 or 1 times and return True otherwise return False
There are several implementations you could use for this, one that I see which avoids applying length to a potentially infinite list is
atmostonce xs y
= (<= 1)
$ length
$ take 2
$ filter (== y) xs
This removes all elements from xs that are not equal to y, then takes at most 2 of those (take 2 [1] == [1], take 2 [] == []), calculates the length (it's safe to use here because we know take 2 won't return an infinite list), then checks if that is no more than 1. Alternatively you could solve this using direct recursion, but it would be best to use the worker pattern:
atmostonce = go 0
where
go 2 _ _ = False
go n [] _ = n <= 1
go n (x:xs) y =
if x == y
then go (n + 1) xs y
else go n xs y
The n <= 1 clause could be replaced by True, but ideally it'll short-circuit once n == 2, and n shouldn't ever be anything other than 0, 1, or 2. However, for your implementation I believe you are looking for the elem function:
elem :: Eq a => a -> [a] -> Bool
atmostonce [] y = True
atmostonce (x:ls) y
| (x == y) && (y `elem` ls) = False
| otherwise = True
But this won't return you the value you want, since atmostonce [1, 2, 2, 2] 2 would return True. Instead, you'd need to do recursion down the rest of the list if x /= y:
atmostonce (x:ls) y
| (x == y) && (y `elem` ls) = False
| otherwise = atmostonce ls y
You can do this using the elem function:
atmostonce:: [Int] -> Int -> Bool
atmostonce [] y = True
atmostonce (x:lx) y | x /= y = atmostonce lx y
| otherwise = not $ elem y lx
You better first check if the element x is not equal to y. If that is the case, you simply call the recursive part atmostonce lx y: you thus search further in the list.
In case x == y, (the otherwise case), you need to check if there is another element in lx (the remainder of the list), that is equal to x. If that is the case, you need to return False, because in that case there are multiple instances in the list. Otherwise you return True.
Furthermore you can generalize your function further:
atmostonce:: (Eq a) => [a] -> a -> Bool
atmostonce [] y = True
atmostonce (x:lx) y | x /= y = atmostonce lx y
| otherwise = not $ elem y lx
Eq is a typeclass, it means that there are functions == and /= defined on a. So you can call them, regardless of the real type of a (Int, String, whatever).
Finally in the first case, you can use an underscore (_) which means you don't care about the value (although in this case it doesn't matter). You can perhaps change the order of the cases, since they are disjunct, and this makes the function syntactically total:
atmostonce:: (Eq a) => [a] -> a -> Bool
atmostonce (x:lx) y | x /= y = atmostonce lx y
| otherwise = not $ elem y lx
atmostonce _ _ = True
The existing answers are good, but you can use dropWhile to do the part that's currently done via manual recursion:
atMostOnce xs y =
let afterFirstY = drop 1 $ dropWhile (/= y) xs
in y `notElem` afterFirstY

Getting parse error while doing list comprehensions in haskell

I'm writing a function like this:
testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
let t = [ r | (x,y) <- zip lst1 lst2, let r = if y == 0 && x == 2 then 2 else y ]
let t1 = [ w | (u,v) <- zip t (tail t), let w = if (u == 2) && (v == 0) then 2 else v]
head t : t1
What the first let does is: return a list like this: [2,0,0,0,1,0], from the second let and the following line, I want the output to be like this: [2,2,2,2,1,0]. But, it's not working and giving parse error!!
What am I doing wrong?
There are two kinds of lets: the "let/in" kind, which can appear anywhere an expression can, and the "let with no in" kind, which must appear in a comprehension or do block. Since your function definition isn't in either, its let's must use an in, for example:
testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
let t = [ r | (x,y) <- zip lst1 lst2, let r = if y == 0 && x == 2 then 2 else y ] in
let t1 = [ w | (u,v) <- zip t (tail t), let w = if (x == 2) && (y == 0) then 2 else y] in
return (head t : t1)
Alternately, since you can define multiple things in each let, you could consider:
testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
let t = [ r | (x,y) <- zip lst1 lst2, let r = if y == 0 && x == 2 then 2 else y ]
t1 = [ w | (u,v) <- zip t (tail t), let w = if (x == 2) && (y == 0) then 2 else y]
in return (head t : t1)
The code has other problems, but this should get you to the point where it parses, at least.
With an expression formed by a let-binding, you generally need
let bindings
in
expressions
(there are exceptions when monads are involved).
So, your code can be rewritten as follows (with simplification of r and w, which were not really necessary):
testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
let t = [ if y == 0 && x == 2 then 2 else y | (x,y) <- zip lst1 lst2]
t1 = [ if (v == 0) && (u == 2) then 2 else v | (u,v) <- zip t (tail t)]
in
head t : t1
(Note, I also switched u and v so that t1 and t has similar forms.
Now given a list like [2,0,0,0,1,0], it appears that your code is trying to replace 0 with 2 if the previous element is 2 (from the pattern of your code), so that eventually, the desired output is [2,2,2,2,1,0].
To achieve this, it is not enough to use two list comprehensions or any fixed number of comprehensions. You need to somehow apply this process recursively (again and again). So instead of only doing 2 steps, we can write out one step, (and apply it repeatedly). Taking your t1 = ... line, the one step function can be:
testing' lst =
let
t1 = [ if (u == 2) && (v == 0) then 2 else v | (u,v) <- zip lst (tail lst)]
in
head lst : t1
Now this gives:
*Main> testing' [2,0,0,0,1,0]
[2,2,0,0,1,0]
, as expected.
The rest of the job is to apply testing' as many times as necessary. Here applying it (length lst) times should suffice. So, we can first write a helper function to apply another function n times on a parameter, as follows:
apply_n 0 f x = x
apply_n n f x = f $ apply_n (n - 1) f x
This gives you what you expected:
*Main> apply_n (length [2,0,0,0,1,0]) testing' [2,0,0,0,1,0]
[2,2,2,2,1,0]
Of course, you can wrap the above in one function like:
testing'' lst = apply_n (length lst) testing' lst
and in the end:
*Main> testing'' [2,0,0,0,1,0]
[2,2,2,2,1,0]
NOTE: this is not the only way to do the filling, see the fill2 function in my answer to another question for an example of achieving the same thing using a finite state machine.

Haskell program that gives pretty prime numbers

I've made a haskell program that computes pretty prime numbers. Pretty primes are primes that are very close to a power of 2. You give 2 numbers for example: 10 and 20 then it returns 17 because 17 is the closest to a power of 2. 17 - 16 = 1 so it is the closest.
I've made this:
EDIT: I've rewrote the primefunction like this and e verw function but still getting -1.
-- Geeft priemgetallen terug tussen de 2 grenzen
-- English: Gives primenumbers between 2 numbers
priemgetallen :: Int->[Int]
priemgetallen b = take b (zeef [2..])
where zeef (p:xs) = p : zeef [x | x<-xs, (mod x p) /= 0]
-- Geeft machten terug tussen de 2 grenzen
-- English: Gives powers of 2 between 2 numbers
machten :: Int->Int->[Int]
machten a b
| a <= 2 = 2:[2^x| x<-[2..b], (2^x) `mod` 2 == 0, 2^x < b, 2^x > a]
| otherwise = [2^x| x<-[2..b], (2^x) `mod` 2 == 0, 2^x < b, 2^x > a]
-- English: the start of the function
prettyprime :: Int->Int->Int
prettyprime a b = vergelijk ( verw a (priemgetallen b)) (machten a b)
-- Filter the list
verw :: Int->[Int]->[Int]
verw _ [] = []
verw k (x:xs)
| x > k = [x] ++ verw k xs
| otherwise = verw k xs
-- Vergelijkt alle priemgetallen en geeft welke korste bij het ander ligt
-- English this function must see what primenumber is the closest to a power of 2 but I can't fix it
vergelijk :: [Int]->[Int]->Int
vergelijk [] _ = -1
vergelijk _ [] = -1
vergelijk (x:xs) (y:ys)
| x - y < vergelijk (x:xs) ys = x
| x - y > vergelijk (x:xs) ys = vergelijk xs (y:ys)
| x - y == vergelijk (x:xs) ys = x
main = do
print $ prettyprime 14 20
Can someone help me?
Kind regards,
The incomplete pattern is because you've omitted the case when x - y == vergelijk (x:xs) ys. The compiler is capable of warning you about this if you add -fwarn-incomplete-patterns and convert your guards into a real case:
vergelijk (x:xs) (y:ys) = case compare (x - y) (vergelijk (x:xs) ys) of
LT -> x
-- you will get a warning about having no case for EQ
GT -> vergelijk xs (y:ys)
As a bonus, this version is much less likely to recompute the recursive call, especially on low optimization levels.

Detecting cyclic behaviour in Haskell

I am doing yet another projecteuler question in Haskell, where I must find if the sum of the factorials of each digit in a number is equal to the original number. If not repeat the process until the original number is reached. The next part is to find the number of starting numbers below 1 million that have 60 non-repeating units. I got this far:
prob74 = length [ x | x <- [1..999999], 60 == ((length $ chain74 x)-1)]
factorial n = product [1..n]
factC x = sum $ map factorial (decToList x)
chain74 x | x == 0 = []
| x == 1 = [1]
| x /= factC x = x : chain74 (factC x)
But what I don't know how to do is to get it to stop once the value for x has become cyclic. How would I go about stopping chain74 when it gets back to the original number?
When you walk through the list that might contain a cycle your function needs to keep track of the already seen elements to be able to check for repetitions. Every new element is compared against the already seen elements. If the new element has already been seen, the cycle is complete, if it hasn't been seen the next element is inspected.
So this calculates the length of the non-cyclic part of a list:
uniqlength :: (Eq a) => [a] -> Int
uniqlength l = uniqlength_ l []
where uniqlength_ [] ls = length ls
uniqlength_ (x:xs) ls
| x `elem` ls = length ls
| otherwise = uniqlength_ xs (x:ls)
(Performance might be better when using a set instead of a list, but I haven't tried that.)
What about passing another argument (y for example) to the chain74 in the list comprehension.
Morning fail so EDIT:
[.. ((length $ chain74 x x False)-1)]
chain74 x y not_first | x == y && not_first = replace_with_stop_value_:-)
| x == 0 = []
| x == 1 = [1]
| x == 2 = [2]
| x /= factC x = x : chain74 (factC x) y True
I implemented a cycle-detection algorithm in Haskell on my blog. It should work for you, but there might be a more clever approach for this particular problem:
http://coder.bsimmons.name/blog/2009/04/cycle-detection/
Just change the return type from String to Bool.
EDIT: Here is a modified version of the algorithm I posted about:
cycling :: (Show a, Eq a) => Int -> [a] -> Bool
cycling k [] = False --not cycling
cycling k (a:as) = find 0 a 1 2 as
where find _ _ c _ [] = False
find i x c p (x':xs)
| c > k = False -- no cycles after k elements
| x == x' = True -- found a cycle
| c == p = find c x' (c+1) (p*2) xs
| otherwise = find i x (c+1) p xs
You can remove the 'k' if you know your list will either cycle or terminate soon.
EDIT2: You could change the following function to look something like:
prob74 = length [ x | x <- [1..999999], let chain = chain74 x, not$ cycling 999 chain, 60 == ((length chain)-1)]
Quite a fun problem. I've come up with a corecursive function that returns the list of the "factorial chains" for every number, stopping as soon as they would repeat themselves:
chains = [] : let f x = x : takeWhile (x /=) (chains !! factC x) in (map f [1..])
Giving:
take 4 chains == [[],[1],[2],[3,6,720,5043,151,122,5,120,4,24,26,722,5044,169,363601,1454]]
map head $ filter ((== 60) . length) (take 10000 chains)
is
[1479,1497,1749,1794,1947,1974,4079,4097,4179,4197,4709,4719,4790,4791,4907,4917
,4970,4971,7049,7094,7149,7194,7409,7419,7490,7491,7904,7914,7940,7941,9047,9074
,9147,9174,9407,9417,9470,9471,9704,9714,9740,9741]
It works by calculating the "factC" of its position in the list, then references that position in itself. This would generate an infinite list of infinite lists (using lazy evaluation), but using takeWhile the inner lists only continue until the element occurs again or the list ends (meaning a deeper element in the corecursion has repeated itself).
If you just want to remove cycles from a list you can use:
decycle :: Eq a => [a] -> [a]
decycle = dc []
where
dc _ [] = []
dc xh (x : xs) = if elem x xh then [] else x : dc (x : xh) xs
decycle [1, 2, 3, 4, 5, 3, 2] == [1, 2, 3, 4, 5]

Resources