Haskell递归空间泄漏

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

[更新]

因此,我修改了代码,使其更具可读性。 函数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)) 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强制求值并不会改变堆泄漏。