【问题标题】:Haskell recursion space leakHaskell 递归空间泄漏
【发布时间】:2012-02-07 16:23:14
【问题描述】:

[更新]

所以我更改了代码以使其更具可读性。 函数 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) 的输出。 Heap 中充满了 IntSet。

【问题讨论】:

  • ABCD 应该是函数吗?将它们写成大写会使它们看起来像构造函数。 X 的相关性如何?
  • 对不起。 A、B、C 和 D 是函数。一些可能的其他表示需要构造函数 X。
  • 由于a (c u) f l是结果,只能从a外部强制求值。要识别泄漏,我们必须查看更多代码。
  • 现在我发布了更多代码。你是什​​么意思评估只能从外部强制?
  • 您是否知道使用pattern guards 可以以一种不那么尴尬的方式编写这样的案例结构?而且,在您现在拥有的代码示例中,a (c u) f l 是什么?

标签: haskell case tail-recursion


【解决方案1】:

如果c 类似于(1+),那么当您建立一个thunk (1+(1+(1+...))) 链时,这可能会导致泄漏。避免这种情况的方法是使用seq:

let k' = c u in k' `seq` a k' f l

seq 将在评估 a k' f l 之前强制评估 k',因此这将在许多情况下处理空间泄漏。

但是,seq 不是万能药,您应该阅读其proper use 并避免使用misusing it

【讨论】:

  • 在这种情况下,函数 c 计算一个新列表,可能是一个更小的列表
  • @tomic84:这仍然会导致一系列 thunk 建立 (c (c (c (c (c ... ))))),因为 u 的值在传递之前从未被强制..
  • 这对我来说很有意义,但尝试使用 seq 强制评估并不会改变堆泄漏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
相关资源
最近更新 更多