Haskell递归空间泄漏
[更新] 因此,我修改了代码,使其更具可读性。 函数dpfsSat有两个参数,klauselMenge是一个包含X元素的庞大集合。 在递归过程中,klauselMenge应该通过一些函数来减少Haskell递归空间泄漏,haskell,case,tail-recursion,Haskell,Case,Tail Recursion,[更新] 因此,我修改了代码,使其更具可读性。 函数dpfsSat有两个参数,klauselMenge是一个包含X元素的庞大集合。 在递归过程中,klauselMenge应该通过一些函数来减少 import qualified Data.IntSet as Set import qualified Data.IntMap as IntMap import qualified Data.Vector as V data X = Xin !(Int,(Set.IntSet)) derivi
import qualified Data.IntSet as Set
import qualified Data.IntMap as IntMap
import qualified Data.Vector as V
data X
= Xin !(Int,(Set.IntSet)) deriving (Eq,Show,Ord)
type Klausel = [Atom]
type KlauselMenge = [Klausel]
dpfsSat :: Int -> KlauselMenge -> Klausel
dpfsSat fset klauselMenge = dpfsSat' fset klauselMenge []
where
dpfsSat' :: Int -> KlauselMenge -> Klausel -> Klausel
dpfsSat' _ [] l = resolveDuplicateLiterals l
dpfsSat' f k l
| f `seq` k `seq` l `seq` False = undefined
| [] `elem` k = []
| ok1 = dpfsSat' f rTF l
| ok2 = dpfsSat' f (substituteSimilarUnits (atomToTupel v2) k) l
| ok3 = dpfsSat' f (resolveUnit1 v3 k ) ((Xin v3):l)
| ok4 = dpfsSat' f (resolvePureLiteral v4 k) ((Xin v4):l)
| otherwise = case (dpfsSat' f (resolveUnit1 minUnit k) ((Xin minUnit): l)) of
[] -> dpfsSat' f ( resolveUnit1 kompl k) ((Xin kompl): l)
xs -> xs
where
rTF = resolveTrueFalse f v1 k
minUnit = findBestLiteral4 k
kompl = (fst minUnit,Set.difference (Set.fromList [1..f]) (snd minUnit))
fTF = findTrueFalse4 f k
fSU = findSimilarAtomUnits f k
fU = findUnit' k
fP = findPureLiteral k
ok1 = maybeToBool fTF
ok2 = maybeToBool fSU
ok3 = maybeToBool fU
ok4 = maybeToBool fP
v1 = expectJust fTF
v2 = expectJust fSU
v3 = expectJust fU
v4 = expectJust fP
maybeToBool :: Maybe a -> Bool
maybeToBool (Just x) = True
maybeToBool Nothing = False
expectJust :: Maybe a -> a
expectJust (Just x) = x
expectJust Nothing = error "Unexpected Nothing"
因为我不允许上传图像,所以我写堆配置文件(-hy)的输出。
堆中充满了IntSet。如果
c
类似于(1+)
,那么在构建一个thunk链时,这可能会导致泄漏(1+(1+(1+…))
。避免这种情况的方法是使用seq
:
let k' = c u in k' `seq` a k' f l
seq
将强制在可以计算k'f l
之前计算k'
,因此这将在许多情况下处理空间泄漏
然而,
seq
并不是万能药,你应该仔细阅读它并避免。如果c
类似于(1+)
,那么这可能会导致泄漏,因为你建立了一个thunks链(1+(1+…)
。避免这种情况的方法是使用seq
:
let k' = c u in k' `seq` a k' f l
seq
将强制在可以计算k'f l
之前计算k'
,因此这将在许多情况下处理空间泄漏
然而,
seq
并不是万能药,你应该仔细阅读它并避免。a、B
、C
和D
应该是功能吗?用大写字母书写会使它们看起来像构造函数。那么X
有什么关系呢?很抱歉。A、 B、C和D是函数。构造函数X对于某些可能的其他表示是必需的。由于a(cu)f l
是结果,因此只能从a
外部强制对其求值。为了识别泄漏,我们必须看到更多的代码。现在我发布了更多的代码。你是什么意思,评估只能从外部强制执行?你知道这样的案例结构可以用一种不那么尴尬的方式编写吗?在你现在看到的代码示例中,这个a(cuf)f l
是什么?a
、B
、c
和D
应该是函数吗?用大写字母书写会使它们看起来像构造函数。那么X
有什么关系呢?很抱歉。A、 B、C和D是函数。构造函数X对于某些可能的其他表示是必需的。由于a(cu)f l
是结果,因此只能从a
外部强制对其求值。为了识别泄漏,我们必须看到更多的代码。现在我发布了更多的代码。你是什么意思,评估只能从外部强制执行?你知道这样的案例结构可以用一种不那么尴尬的方式编写吗?在现在的代码示例中,这是什么?在这种情况下,函数c计算一个新列表,可能是一个较小的列表one@tomic84:这仍然会导致一连串的砰砰声积聚起来(c(c(c(c)(c…))))
因为u
的值在传递之前从来不会被强制。这对我来说是有意义的,但是尝试用seq强制求值并不会改变堆泄漏。在这种情况下,函数c计算一个新列表,可能更小one@tomic84:这仍然会导致一连串的砰砰声积聚起来(c(c(c(c)(c…))))
因为u
的值在传递之前从未被强制。这对我来说是有意义的,但是尝试使用seq强制求值并不会改变堆泄漏。