I've written a simple function in haskell that is non tail recursive that sums up the values inside a list where:
nonTailRecursiveSum :: [Integer] -> Integer
nonTailRecursiveSum [] = 0 --base case
nonTailRecursiveSum (x:xs) = x + sum xs
But what I'm trying to do now is to implement the same function but using tail recursion. For what i know, tail recursion performs the recursive call at the final step so i tried something like:
tailRecursiveSum :: [Integer] -> Integer
tailRecursiveSum [] = 0
tailRecursiveSum (x:xs) = aux_f(x) + tailRecursiveSum xs
.
.
But i got lost in the midway as I'm not familiar with tail recursion in Haskell. Could anyone assist me on the continuation of the tail recursive version of the code?
Playing with it for a bit,
sum (x:y:xs) = x + sum (y:xs)
= x + (y + sum xs)
= (x + y) + sum xs
g a b = a + sum b
sum (x:y:xs) = g x (y:xs)
= x + g y xs
= g (x+y) xs -- !!!
the last one is in tail recursive form! We thus just define
sum xs = g 0 xs
where
g acc [] = ...
g acc (x:xs) = g (acc + ...) ...
Fill in the blanks!
Related
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.
I am currently trying to implement the Sieve of Atkin in Haskell
In step 3 on the Wikipedia article on the Sieve of Atkin I need to find the number of Integer solutions to multiple equations.
However my solution to the first of these equations (4x² + y² = n, x > 0, y > 0
with n being a entry in a list of positive Integers) produces an infinite loop upon a query with any n.
This is my code for this part of the problem so far:
eq1 :: Integer -> Integer
eq1 n = eq1_ n []
eq1_ :: Integer -> [(Integer, Integer)] -> Integer
eq1_ n list | (x > 0) && (y > 0) && (n == 4*(x^2) + (y^2)) && (notElem ((x,y)) list) = eq1_ n ([(x, y)] ++ list)
| otherwise = toInteger (length list)
where
x = floor (sqrt (fromIntegral ((n - y^2) `div` 4)))
y = floor (sqrt (fromIntegral (n - 4*(x^2))))
It is loaded just fine by WinGHCi, but when I query e.g. eq1 0 it just stays in an infinite loop and has to be interrupted before producing an answer. I suspect it goes in a loop between the two assignments of x and y.
How can I prevent this? Is this even possible?
Edit: Realised where the infinite loop must be.
I'm going to start by reformatting your code a tad to make it more readable. Line breaks are helpful! Also, the order of operations can reduce the weight of parentheses. Side note:
f x | e1 && e2 && e3 = e4
can also be written
f x | e1
, e2
, e3
= e4
which may be easier on the eyes.
eq1 :: Integer -> Integer
eq1 n = eq1_ n []
eq1_ :: Integer -> [(Integer, Integer)] -> Integer
eq1_ n list
| x > 0 &&
y > 0 &&
n == 4*x^2 + y^2 &&
notElem (x,y) list
= eq1_ n ([(x, y)] ++ list)
| otherwise
= toInteger (length list)
where
isqrt = floor . sqrt . fromIntegral
x = isqrt $ (n - y^2) `div` 4
y = isqrt $ n - 4*(x^2)
Now I can immediately see that the logic is wonky. Given n, you calculate x and y. Then you either stop or call the function recursively. On the recursive call, however, you're guaranteed to stop! So even if you were otherwise right, you'd definitely have a semantic problem, always returning 0 or 1.
But as you've seen, that's not the only problem. You're also defining x in terms of y and y in terms of x. Now there are important situations where such mutual recursion is useful. But when the mutually recursive values are "atomic" things like integers, you're sure to get an infinite loop. Haskell won't solve the equations for you; that's your job!
Here's my suggestion:
Start with a brute force list comprehension solution:
sols n
= [(x,y)
|x <- takeWhile (\p -> 4 * p^2 < n) [1..]
,y <- takeWhile (\q -> f x y <= n) [1..]
,f x y = n]
where
f x y = 4*x^2+y^2
Next, you can use an approximate integer square root to narrow the search space for y:
sols n
= [(x,y)
|x <- takeWhile (\p -> 4 * p^2 < n) [1..]
,y <- takeWhile
(\q -> f x y <= n)
[floor(sqrt(fromIntegral(n-4*x^2)))..]
,f x y = n]
where
f x y = 4*x^2+y^2
I would like to count the number of positive integers/elements in the list. This returns the elements with positive values, how can I count the elements? would like to construct something like count(array(...)).
I would like to see a version with i++ and foldl. That would be very helpful.
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
Here's a hint: follow the same recursion scheme as before, but return an int at every step.
countPositivesRec :: [Int] -> Int
---
countPositivesRec [] = 0 -- no positives in the empty list
countPositivesRec (x:xs) | x >= 0 = ??
| otherwise = ??
where tl = countPositivesRec xs
One you solve this, it can be rewritten using foldr, if you want.
If you really want to use foldl instead, I would suggest you start by defining a function f such that
f (f (f 0 x0) x1) x2
evaluates to the number of positives in x0,x1,x2. Then you can use foldl f 0 inputList
The function you've written is filter (>=0). As Paul pointed out, the only step remaining is to count and length does that. We can transform the function step by step:
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
Observe that xs is only used in the transformed form tl. That's what makes this a right fold.
onlypos1 = foldr maybekeep []
where maybekeep x tl | x >= 0 = x : tl
| otherwise = tl
This operation is known as a filter, keeping only some parts:
onlypos2 = filter dowekeep
where dowekeep x = x >= 0
onlypos3 = filter (\x -> x >= 0)
onlypos4 = filter (>= 0)
But this is of course only one of many possible approaches. For instance, strictness analysis can lead to the conclusion that length is better implemented as foldl' (\a _ -> succ a) 0 than foldr (\_ a -> succ a) 0. Indeed, that is its basic form in the Prelude:
length = foldl' (\c _ -> c+1) 0
We see that the combining function of length ignores the value of one argument, merely requires it to be there. This can naturally be merged with our condition that only some elements count:
lengthFilter1 = length . filter
lengthFilter2 pred = foldl' predCount 0
where predCount c x = if pred x then c+1 else c
countNonNegative = lengthFilter2 nonNegative
where nonNegative x = x >= 0
Incidentally, 0 isn't positive. It's non-negative.
In the end, Haskell's lazy lists mean we can use them to fuse traversals; length . filter (>=0) will only read the input list once, because the only reason it's processing results from filter is that length consumes them. The filtered list never exists as a fully expanded structure, unlike e.g. Python or PHP. This form is likely one of the most readable, but others exist, e.g.:
countNonNegatives xs = sum [1 | x <- xs, x >= 0]
You have
filtering p cons x r = if | p x -> cons x r | otherwise -> r
countPositives = length
. filter (> 0)
= foldr (\x r -> r + 1) 0 -- r++
. foldr (filtering (> 0) (:) ) []
= foldr (filtering (> 0) (\x r -> r + 1)) 0
(since folds fuse by composing their reducer transformers, a-la "fold replaces the cons with a reducer operation, so why create the cons in the first place if it gonna be replaced anyway"), and
filtering (> 0) (\x r -> r + 1) x r
= if | (> 0) x -> (\x r -> r + 1) x r | otherwise -> r
= if | x > 0 -> r + 1 | otherwise -> r
and thus, a version with fold and increment that you wanted,
countPositives = foldr (\x r -> if | x > 0 -> r + 1 | otherwise -> r) 0 -- r++
You can take it from here.
I'm supposed to write a function that will contain the product of each previous multiplication with that number
Basically this:
> productFromLeftToRight [2,3,4,5]
[120,60,20,5]
I'm supposed to use High Order functions, so folds and such. I'm thinking of using a foldr to traverse through the list with a lambda expression. This is what I'm thinking:
> productFromLeftToRight nums = foldr (\x acc -> [x] * acc ++ acc) [] nums
Since it would unravel like f(2 (f 3 (f 4 (f 5 [])))) I would think I'm right, but I get the whole print error and I don't know how to multiply a number with the first element of acc ( head acc doesn't work)
productFromLeftToRight = scanr1 (*)
or
productFromLeftToRight' =
snd . foldr (\x (acc,lst) -> (x * acc, x * acc : lst)) (1,[])
productFromLeftToRight nums =
init $ foldr (\x lst -> x * head lst : lst) [1] nums
The idea is to use a dummy element 1 to the answer list and remove it in the end.
Here's another one that doesn't do any post-processing after the foldr:
productFromLeftToRight = foldr (\n ps -> n * foldr const 1 ps : ps) []
Here, the inner foldr const 1 is acting as a non-partial head function to get the first element of ps:
foldr const 1 (x:xs) = const x (foldr const 1 xs) = x
foldr const 1 [] = 1
The goal is to validate a list of numbers (credit card number for example ) to first initiate it, reverse it, and then double it, and that would give the sum. Then it would tell if it is valid or in-valid. I have written the code but it wont compile right. It keeps saying this: test.hs:22:1: Parse error in pattern: sumNum.
Here is my code:
main = do
toDigits :: Integer -> [Integer]
toDigitsRev :: Integer -> [Integer]
toDigitsRev n
where
n <= 0 = []
otherwise = n `mod` 10 : toDigitsRev (n `div` 10)
toDigits = reverse . toDigitsRev
double :: [Integer] -> [Integer]
double [] = []
double (x:[]) = [x]
double (x:y:zs) = x : (2 * y) : double zs
doubleRev = reverse . double . reverse
sumNum :: [Integer] -> Integer
sumNum [] = 0
sumNum (x:xs)
x < 10 = x + sumNum xs
otherwise = (x `mod` 10) + (x `div` 10) + sum xs
validate :: Integer -> Bool
validate n = (mod (sumNum (doubleRev (toDigits n))) 10) == 0
You forgot the guard bars:
sumNum (x:xs)
| x < 10 = ...
| otherwise = ...
Without the pipe characters, the compiler sees it as sumNum (x:xs) x < 10 = x + sumNum xs, which doesn't make sense as a pattern, since it seems to suggest you have 3 more arguments, namely x, < and 10, although < does not make sense as a name by itself. Alternatively you could just skip the guard altogether, since
> map (`mod` 10) [0..9] == [0..9]
True
> map (`div` 10) [0..9] == replicate 10 0
True
So all you save is a little efficiency. Since you're working with very small inputs you don't really need to worry about this, so you could just use sumNum [] = 0; sumNum (x:xs) = (x `mod` 10) + (x `div` 10) + sum xs, or more simply sumNum = sum . map (\x -> (x `mod` 10) + (x `div` 10)).