I have a example of accu version of recursion.
Normal recursion:
fib n = if n== 0 then 1 else if n==1 then 1 else fib(n-1) + fib (n-2)
Accu recursion:
fib n fibPOM n 1 1
fibPOM n f1 f2 = if n ==1 then f1 else fibPOM (n-1) (f1+f2) f1
And i must do the same with this(a^n recursion):
ff a n = if n==0 then 1 else if n==1 then a else a * ff a (n-1)
But i have no idea what i must do to get a^n accu recursion.
Here's a hint: add an accumulator argument acc
ff a n = ffACC a n (some initial accumulator value)
ffACC a n acc =
if n==0 then ...
else if n==1 then ...
else ...
Make sure that in each ... all the recursive calls are tail calls. That is, return ffACC (new a) (new n) (new acc), not something like value * ffACC ....
You start with an initial value 1: ff a n = ffAccu a n 1, then call the recursion as
ffAccu a n m = if n == 0 then m else (ffAccu a (n-1) (a*m))
(Note: The if then else construct might be written more cleanly by using pattern matching, as in
ffAccu a 0 m = m
ffAccu a n m = ffAccu a (n-1) (a*m)
)
Related
In the book of The Haskell Road to Logic, Math and Programming by Doets et.al., at page 103, it is given that
prime :: Integer -> Bool
prime n | n < 1 = error "not a positive integer"
| n == 1 = False
| otherwise = ldp n == n where
ldp = ldpf primes
ldpf (p:ps) m | rem m p == 0 = p
| p^2 > m = m
| otherwise = ldpf ps m
primes = 2 : filter prime [3..]
However, isn't the logic of this function circular ? I mean I think I'm quite comfortable with recursive functions, but I do not think that this is a recursive function. Even if it is, I'm not able to comprehend the logic of it, so my question is that how to read the logic of such a function.
Edit:
The reason why I'm confused is prime function uses the list primes, but to generate that list, we also use the function prime, so it seems that there is a circular logic, or I just do not understand recursive functions with lazy evaluation.
The ldp n == n condition can be equivalently re-written as
ldpf primes n == n
=
null [() | p <- takeWhile (\p -> p^2 <= n) primes, rem n p==0]
=
and [rem n p > 0 | p <- takeWhile (\p -> p^2 <= n) primes]
so for any given n, the call prime n = ldp n == n only needs to generate the list
primes = 2 : filter prime [3..]
= 2 : filter (\n -> ldpf primes n == n) [3..]
= 2 : filter (\n -> and [rem n p > 0
| p <- takeWhile (\p -> p^2 <= n) primes])
[3..]
up to the smallest prime number q > floor (sqrt $ fromIntegral n), and for that only the primes not greater than q's square root are needed. And to generate those, only the numbers not greater than the square root of that were needed. Pretty soon we end up not needing any primes at all, e.g.
prime 3
=
ldpf primes 3 == 3
=
and [rem 3 p > 0 | p <- takeWhile (\p -> p^2 <= 3) (2 : filter prime [3..])]
=
and [rem 3 p > 0 | p <- takeWhile (<= 3) (4 :
map (\p -> p^2) (filter prime [3..]))]
=
and [rem 3 p > 0 | p <- []]
=
and []
=
True
because 2 already fails the predicate: (2^2 <= 3) = (4 <= 3) = False.
And when testing 4, primes will be probed for containing the number 3, but that's OK as we've just seen above:
prime 4
=
and [rem 4 p > 0 | p <- takeWhile (\p -> p^2 <= 4) primes]
=
and [rem 4 p > 0 | p <- takeWhile (<= 4) (4 :
map (\p -> p^2) (filter prime [3..]))]
=
and [rem 4 p > 0 | p <- 4 : takeWhile (<= 4) (9 :
map (\p -> p^2) (filter prime [4..]))]
=
and [rem 4 p > 0 | p <- 4 : []]
=
False
and we can check it at the GHCi prompt after that,
> :sprint primes
2 : 3 : _
(for the above to work you'll need to take primes out of the prime function and make it a top-level entity in its own right).
I am stuck with the variable not in scope: m error.
This is supposed to be a code to sum n numbers in a tail recursion way.
zum :: Integer-> Integer
zum n = add_sum m n where
add_sum :: Integer-> Integer-> Integer
add_sum m n
| n == 0 = m
| otherwise = add_sum (m+n) (n-1)
In the second line of your code
zum n = add_sum m n where
'm' is not defined. Perhaps it was intended that instead of an 'm', there needs to be 0 there.
perhaps cleaner this way?
sum n = go 0 n
where go m 0 = m
go m n = go (m+n) (n-1)
> sum 4
10
Hello I am trying to make a function goldbach :: Integer -> Bool for interval [4..n] that should return True only if all elements in that interval is even and can be summed from two prim numbers. So far I have done this.
goldbach::Integer->Bool
goldbach n
|goldbach2 n == ??? = goldbach (n-2)
|n==4 = True
|otherwise = False
goldbach2 :: Integer -> (Integer, Integer)
goldbach2 a = head $
filter (\(x,y) -> isPrime x && isPrime y) $
map (\e -> (e, a - e)) [3,5..a `div` 2]
where
factors a = filter (isFactor a) [2..a-1]
isFactor a b = a `mod` b == 0
isPrime a = null $ factors a
Function golbach2 result looks like this goldbac2 28 = (5, 23). How should I chek in my 3rd line goldbach2 n == ??? = goldbach (n-2) if result of goldbach2 n is correct and gives me two prim numbers?
If I understand it correctly, you want something like:
| let (n1, n2) = goldbach2 n in n == n1 + n2 = goldbach (n-2)
I would write this like
goldbachInterval n = all goldbach [4,6 .. n]
where
goldbach k = .... -- property of being a golbach number
How do I do the induction to establish the statement moll n = doll n, with
moll 0 = 1 --(m.1)
moll n = moll ( n-1) + n --(m.2)
doll n = sol 0 n --(d.1)
where
sol acc 0 = acc +1 --(d.2)
sol acc n = sol ( acc + n) (n-1) -- ? (d.2)
I tried to prove the base case for n = 0
doll 0 = (d.2) = 1 = (m.1) = moll 0 , which is correct.
Now for n+1, show that
moll 2n = doll (n + 1)
=> doll (n + 1) = (d.2) = soll (acc + n + 1) n
But what now? How can I simplify it any further?
You've got a mistake in your n+1 step. I suspect this is because you're new to Haskell and its precedence rules.
moll (n+1) is not, as you write moll 2n - I'm assuming that by that you mean moll (2*n), since moll 2n is a haskell syntax error.
In any case, moll (n+1) is in fact moll n + n + 1, or, with extra parentheses added just to be explicit:
(moll n) + (n + 1)
That is, you apply moll to n and then you add n + 1 to the result of that.
From here you should be able to apply the induction hypothesis and go forward.
More explicitly, since you seem to still be having trouble:
moll (n+1) == (moll n) + (n + 1) (by m.2)
== (doll n) + (n + 1) (by induction hypot.)
== (sol 0 n) + (n + 1) (by d.1)
Now, as a lemma:
sol x n == (sol 0 n) + x
This can be proved by induction on n. It's obviously true for n equal to 0.
For the lemma's induction step:
sol x (n+1) == (sol (x + (n+1)) n) (By d.2, for (n+1) > 0)
== (sol 0 n) + (x + (n+1)) (By the induction hypot.)
== (sol 0 n) + (n+1) + x (This is just math; re-arranging)
== ((sol 0 n) + (n+1)) + x
== (sol (n+1) n) + x (By the induction hypot. again)
== (sol 0 (n+1)) + x (By d.2 again)
That second time I used the induction hypothesis may seem a bit odd, but remember that the induction hypothesis says:
sol x n == (sol 0 n) + x
For all x. Therefore, I can apply it to anything added to (sol 0 n), including n+1.
Now, back to the main proof, using our lemma:
moll (n+1) == (sol 0 n) + (n + 1) (we had this before)
== sol (n+1) n (by our lemma)
== sol 0 (n+1) (by d.2)
== doll (n+1) (by d.1)
I am studying about haskell recursion. and when i read about recursion topic which talk about this two different type of recursion. i am understand how tail recursion works and its step to be done. i am not understand how is primitive recursion done in background. can anyone here help explain more about primitive and given some example ?
For example : tail recursion
sum:: [Int] -> Int
sum [] = 0
sum (x:xs) = x+ (sum xs)
process of sum [1,2,3,4]:
= 1 + sum[2,3,4]
= 1 + (2 + sum [3,4] )
= 1 + ( 2 + ( 3 + sum[4]) )
= 1 + (2 + (3 ( 4 + sum[])))
= 1 + (2 + ( 3 + ( 4 + 0 ) ) )
= 10
How does primitive recursion works?
Intuitively, we have tail recursion when we have a recursive function such that, when a recursive call is performed, the result of that call is the result of the function. In a sense, after the recursive call "there is nothing more to be done".
-- tail recursion
f1 n = if ... then ... else f1 (n - 1)
-- not tail recursion
f2 n = if ... then ... else 5 * f2 (n - 1)
Primitive recursion is another beast. We have primitive recursion when every recursive call is done using an argument which is a "direct subterm" of the original one.
-- primitive recursion (& non-tail recursion)
f1 (x:xs) = g x (f1 xs) -- xs is asubterm of x:xs
-- a tree type
data T = K Int T T
-- primitive recursion (& non-tail recursion)
f2 (K n l r) = h n (f2 l) (f2 r) -- l, r are subterms
-- non-primitive recursion (& tail recursion)
f3 (K n l (K m rl rr)) = f3 (K m (K n rl l) rl) -- not a subterm