Haskell 有什么阻止优化尾部递归的吗?

Haskell 有什么阻止优化尾部递归的吗?,haskell,lazy-evaluation,tail-recursion,knapsack-problem,Haskell,Lazy Evaluation,Tail Recursion,Knapsack Problem,我正在用动态编程解决Haskell的背包问题。我的第一次尝试是建立一个二维表格。但当输入较大时(例如,100*3190802表),内存很容易膨胀 知道任何给定的行i只依赖于行(i-1),因此我编写了一个函数,希望利用尾部递归: import Data.Vector (Vector, (!)) import qualified Data.Vector as V -- n items, k capacity, vs values, ws weights ans:: Int -> Int -&

我正在用动态编程解决Haskell的背包问题。我的第一次尝试是建立一个二维表格。但当输入较大时(例如,100*3190802表),内存很容易膨胀

知道任何给定的行
i
只依赖于行
(i-1)
,因此我编写了一个函数,希望利用尾部递归:

import Data.Vector (Vector, (!))
import qualified Data.Vector as V

-- n items, k capacity, vs values, ws weights
ans:: Int -> Int -> Vector Int -> Vector Int -> Int
ans n k vs ws =
    let row = initRow k vs ws
    in  row ! k

initRow :: Int -> Vector Int -> Vector Int -> Vector Int
initRow k vs ws = itbl 1 $ V.replicate (k + 1) 0
    where n = V.length vs
          itbl i row
             | i > n = row
             | otherwise = itbl (i + 1) $ V.generate (k + 1) gen
             where gen w =
                       let w_i = ws ! (i - 1)
                           no_i = row ! w
                           ok_i = row ! (w - w_i) + (vs ! (i - 1))
                       in
                           if w < w_i then no_i
                           else max no_i ok_i
代码中是否有任何东西阻止编译器为尾部递归生成优化代码


--这是一个严格的问题。在中调用
generate

             | otherwise = itbl (i + 1) $ V.generate (k + 1) gen
实际上不会将向量强制放入内存

您可以导入控制.DeepSeq并用严格的应用程序替换
$

             | otherwise = itbl (i + 1) $!! V.generate (k + 1) gen
或者,您可以使用未绑定的向量(可能更快),方法是将import语句更改为

import Data.Vector.Unboxed (Vector, (!))
import qualified Data.Vector.Unboxed as V

(并将所有其他内容保留在原始程序中)。

出于好奇,尝试从
itbl(i+1)$V.generate(k+1)gen
调用中删除
itbl(i+1)(V.generate(k+1)gen)
。我猜,
$
使调用不是尾部递归的。谢谢。但是删除
$
似乎没有帮助。内存使用仍然在增长。我想这是懒惰的问题。在惰性语言中,尾部递归是不够的(也不总是可取的)。请尝试用
$替换
$
。感谢大家指出正确的方向。是的,是关于严格。
import Data.Vector.Unboxed (Vector, (!))
import qualified Data.Vector.Unboxed as V