Reputation: 601
My idea is to do something like:
class Memo1D m where -- for one-Dimensional function
memo1D :: m a -> [a]
instance Memo1D ((->) Int) where
memo1D f = map f [0 ..]
So, to add memoization to a Integer-recursive-problem would be very generic:
fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = (memo_fib !! (n - 1)) + (memo_fib !! (n - 2))
memo_fib = memo1D fib
And furthermore, if I also want to do the memoization in 2-D function, recieve 2 Integer as parameters, I have to add more code (the (Int->Int->)
is error, how to declare it?):
class Memo2D m where
memo2D :: m a -> [[a]]
instance Memo2D (Int -> Int ->) where -- (Int -> Int ->) is error, how to declare the kind that recieve `a` type and then become (Int->Int->a) ?
memo2D f = map (\v -> map v [0 ..]) (map f [0 ..])
And the "2-D fibnacci number" with memoization would be coded like:
fib2 0 0 = 1
fib2 0 1 = 1
fib2 1 0 = 1
fib2 i j = if j > 0 then memo_fib2 !! i !! (j - 1) else 0 +
if j > 1 then memo_fib2 !! i !! (j - 2) else 0 +
if i > 0 then memo_fib2 !! (i - 1) !! j else 0 +
if i > 1 then memo_fib2 !! (i - 2) !! j else 0
memo_fib2 = memo2D fib2
And for 3-D, 4-D, etc. I also have to type corresponding class and instance. Is there a way to make these elegant and effective on multiple-dimension function, in here the multiple-dimension specific for the (Int->Int-> ... -> a) kind function?
Upvotes: 0
Views: 78
Reputation: 27646
How about something like below. However, in practice you could just pick one of the existing memoization libraries from Hackage.
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
class Memo m a where
memo :: m -> a
instance Memo a a where
memo = id
instance (Memo m a) => Memo (Int -> m) [a] where
memo f = map (memo . f) [0..]
fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = memo_fib (n - 1) + memo_fib (n - 2)
memo_fib = (memo fib !!)
fib2 0 0 = 1
fib2 0 1 = 1
fib2 1 0 = 1
fib2 i j = sum . concat $ [ [ memo_fib2 i (j-1) | j > 0 ]
, [ memo_fib2 i (j-2) | j > 1 ]
, [ memo_fib2 (i-1) j | i > 0 ]
, [ memo_fib2 (i-2) j | i > 1 ]
]
memo_fib2 = let tab = memo fib2 in \x y -> tab !! x !! y
Upvotes: 1