Haskell使代数递归的通用化成为通用的

时间:2015-05-15 08:23:43

标签: haskell generics recursion

我的想法是做一些事情:

class Memo1D m where -- for one-Dimensional function
    memo1D :: m a -> [a]

instance Memo1D ((->) Int) where
    memo1D f = map f [0 ..]

因此,将记忆添加到Integer-recursive-problem中将是非常通用的:

fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = (memo_fib !! (n - 1)) + (memo_fib !! (n - 2))
memo_fib = memo1D fib

此外,如果我还想在2-D函数中进行memoization,接收2 Integer作为参数,我必须添加更多代码((Int->Int->)是错误,如何声明它?):< / p>

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 ..])

&#34; 2-D fibnacci数&#34;记忆的编码如下:

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

对于3-D,4-D等,我还必须输入相应的类和实例。 有没有办法在多维度函数上使这些优雅有效,这里是(Int-&gt; Int-&gt; ... - &gt; a)类函数的多维特征?

1 个答案:

答案 0 :(得分:1)

如下所示。但是,在实践中,您可以从Hackage中选择一个现有的memoization库。

{-# 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