I'm trying to find a good way to memoize a function for only part of its domain (non-negative integers) in Haskell, using Data.MemoCombinators.
import Data.MemoCombinators
--approach 1
partFib n | n < 0 = undefined
| otherwise = integral fib n where
fib 0 = 1
fib 1 = 1
fib k = partFib (k-1) + partFib (k-2)
--approach 2
partFib2 n | n < 0 = undefined
| otherwise = fib n
fib = integral fib'
where
fib' 0 = 1
fib' 1 = 1
fib' n = partFib2 (n-1) + partFib2 (n-2)
Approach 1 is how I would like to do it, however, it doesn't seem to work. I assume this is because the fib function is "recreated" every time partFib is called, throwing away the memoization. fib doesn't depend on the input of partFib, so you would assume that the compiler could hoist it, but apparently GHC doesn't work that way.
Approach 2 is how I end up doing it. Eerk, a lot of ugly wiring.
Does anybody know of a better way to do this?
Not quite sure what's "ugly" to your eye, but you can have proper memoization while using only a single top-level identifier by lifting the memoization operation out of the function of n.
partFib3 = \n -> if n < 0 then undefined else fib' n
where fib 0 = 1
fib 1 = 1
fib k = partFib3 (k-1) + partFib3 (k-2)
fib' = integral fib
Hmm what about separating things a bit:
fib 0 = 0
fib 1 = 1
fib x = doFib (x-1) + doFib (x-2)
memFib = Memo.integral fib
doFib n | n < 0 = fib n
| otherwise memFib n
Now you need to use doFib.
There is a combinator in the library for this purpose:
switch :: (a -> Bool) -> Memo a -> Memo a -> Memo a
switch p a b uses the memo table a whenever p gives true and the memo table b whenever p gives false.
Recall that id is technically a memoizer (which does not memoize :-), so you can do:
partFib = Memo.switch (< 0) id Memo.integral fib'
where
...
Related
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)
)
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
So I've been playing with Haskell the past couple of days, and I decided I'd make a basic definition of the Fibonacci sequence. So I wrote this code:
main = do
fib :: (Integral a) => Int -> Int
fib x
| x == 0 = 0
| x == 1 = 1
| x >= 2 = fib (x - 2) + fib (x - 1)
do { print (fib 5) }
And I get an error message saying:
4:17: parse error on input `|'
I suspected tab errors, so I tried every whitespace fix I could find, but I just can't find what's wrong!
EDIT: So I did what people suggested, and I have this code now:
fib :: (Integral a) => Int -> Int
main = do
fib x
| x == 0 = 0
| x == 1 = 1
| x >= 2 = fib (x - 2) + fib (x - 1)
print (fib 5)
And I'm getting the same error.
You should define fib outside of main, not inside it. And then you should remove at least one of the dos from main.
The problem is that you are trying to define the function within do block without actually using any construct for defining things (like let).
Try defining the function outside the block:
fib :: (Integral a) => Int -> Int
fib x | x == 0 = 0
| x == 1 = 1
| x >= 2 = fib (x - 2) + fib (x - 1)
main = print (fib 5)
If you insist on defining the function locally (inside the expression that is formed by statements of the do block):
main = do
let
fib :: (Integral a) => Int -> Int
fib x | x == 0 = 0
| x == 1 = 1
| x >= 2 = fib (x - 2) + fib (x - 1)
print (fib 5)
Notice how let is used to bind a new variable fib to the function you want.
You can also define fib locally to main outside of the do block. Do bear in mind that do is syntactic sugar for the use of various monadic binding functions, and so the syntax accepted within it is not quite the same as that accepted outside it. And, in fact, your main doesn't even require the do block because you just call print rather than chaining any IO actions together.
main = let
fib x | x == 0 = 0
| x == 1 = 1
| x >= 2 = fib (x - 2) + fib (x + 1)
in
print (fib 5)
Or you could use where:
main = print (fib 5)
where
fib x | x == 0 = 0
| x == 1 = 1
| x >= 2 = fib (x - 2) + fib (x + 1)
They're the same, the question is just where the local binding actually goes. let..in gives you a new block where the new bindings are in scope, while where makes its bindings available in the scope of the function it's attached to.
If, as seems eventually likely, you do want a do block as well so you can do multiple IO actions, you can just put that in place of the call to print, like so:
main = let
fib x | x == 0 = 0
| x == 1 = 1
| x >= 2 = fib (x - 2) + fib (x + 1)
in
do print (fib 5)
print (fib 6)
I am relatively new to Haskell and everything I have done has been completed through GHCi, however, now I am trying to compile using GHC, however, I constantly get the error message The IO action ‘main’ is not defined in module ‘Main’, I have tried declaring main = do, however, I receive more errors then, namely parse error on input ‘=’ from the line fib 0 = 1.
Here is the code I am working with:
module Main where
fib :: Integer -> Integer
fib 0 = 1
fib 1 = 1
fib x = fib (x - 1) + fib (x - 2)
Thanks for any help in advance!
You should write something like:
module Main where
fib :: Integer -> Integer
fib 0 = 1
fib 1 = 1
fib x = fib (x - 1) + fib (x - 2)
main :: IO ()
main = do
print $ fib 10
Note: your fib function should not be indented, it should be left aligned.
Because main should be of type IO (). Something like this should work:
main = print $ fib 3
Your entire program should look like this:
module Main where
fib :: Integer -> Integer
fib 0 = 1
fib 1 = 1
fib x = fib (x - 1) + fib (x - 2)
main = print $ fib 3
Notice the space difference between your code and the above one in the fib function.
I have tried declaring main = do
main = do just doesn't make any sense for the compiler. Remember do is a syntax sugar for monads. do is not a valid expression.
I'm trying to transform my recursive Fibonacci function into an iterative solution. I tried the following:
fib_itt :: Int -> Int
fib_itt x = fib_itt' x 0
where
fib_itt' 0 y = 0
fib_itt' 1 y = y + 1
fib_itt' x y = fib_itt' (x-1) (y + ((x - 1) + (x - 2)))
I want to save the result into variable y and return it when the x y matches with 1 y, but it doesn't work as expected. For fib_itt 0 and fib_itt 1, it works correctly, but for n > 1, it doesn't work. For example, fib_rek 2 returns 1 and fib_rek 3 returns 2.
Your algorithm is wrong: in y + (x-1) + (x-2) you only add up consecutive numbers - not the numbers in the fib.series.
It seems like you tried some kind of pair-approach (I think) - and yes it's a good idea and can be done like this:
fib :: Int -> Int
fib k = snd $ fibIt k (0, 1)
fibIt :: Int -> (Int, Int) -> (Int, Int)
fibIt 0 x = x
fibIt k (n,n') = fibIt (k-1) (n',n+n')
as you can see: this passes the two needed parts (the last and second-to-last number) around as a pair of numbers and keeps track of the iteration with k.
Then it just gives back the second part of this tuple in fib (if you use the first you will get 0,1,1,2,3,... but of course you can adjust the initial tuple as well if you like (fib k = fst $ fibIt k (1, 1)).
by the way this idea directly leeds to this nice definition of the fib.sequence if you factor the iteration out to iterate ;)
fibs :: [Int]
fibs = map fst $ iterate next (1,1)
where
next (n,n') = (n',n+n')
fib :: Int -> Int
fib k = fibs !! k