Space Control.Lens.Plated 和 Bound 交互中的泄漏/错误
Space leak / Bug in interaction of Control.Lens.Plated and Bound
使用最新版本的 Bound
和 Control.Lens.Plated
,以下 transform
调用会导致程序无限循环并愉快地消耗我的 RAM。有趣地终止程序会导致打印正确的结果,尽管我不知道为什么。
我已将问题追溯到 Scope
数据类型。删除它会使程序按预期运行。
使用 ./program +RTS -p -h
进行分析显示 Data.Data.Lens.insertHitMap.populate
是有问题的部分。附上一些分析。
这是官方解决方法的预期行为还是可能是错误?
我正在使用 GHC 版本 8.0.2,除 bound-2
之外的所有包都是堆栈 lts-8.17
的一部分。该程序被编译为 ghc test.hs
。启用或禁用优化不会影响问题。
因为我怀疑这是一个错误,所以我在 ekmett
的 bound
存储库(用于交叉引用目的)上为此打开了一个 issue。
-- file: test.hs
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable,
DeriveDataTypeable #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
module Main (main) where
import Bound
import Control.Lens hiding (List)
import Control.Lens.Plated
import Data.Deriving (deriveShow1, deriveEq1)
import Data.Data
import Data.Data.Lens (uniplate)
data Expr a = Var a
| List [Expr a]
| Apply (Expr a) (Expr a)
| Lam (Scope () Expr a)
| Nop
deriving (Functor, Foldable, Traversable, Data)
main = do
print ex
print $ transform removeTest ex
ex :: Expr String
ex = List [Apply (Var "test") $ List [Var "arg1", Var "arg2"]
,Apply (Var "two") (Var "three")]
removeTest :: Expr String -> Expr String
removeTest = \expr -> case expr of
Apply (Var "test") _ -> Nop
_ -> expr
instance Data a => Plated (Expr a) where
plate = uniplate
makeLenses ''Expr
makeBound ''Expr
deriveEq1 ''Expr
deriveShow1 ''Expr
deriving instance Show a => Show (Expr a)
deriving instance Eq a => Eq (Expr a)
输出:
List [Apply (Var "test") (List [Var "arg1",Var "arg2"])
,Apply (Var "two") (Var "three")]
^CList [Nop,Apply (Var "two") (Var "three")]
-- profiterole stats
TOT INH IND
99.9 99.9 .1 MAIN MAIN (0)
99.9 99.9 .1 MAIN MAIN (0)
99.9 99.9 34.0 Main CAF (0)
65.9 65.9 - Data.Data.Lens fromOracle (35)
65.9 65.9 - Data.Data.Lens hitTest (0)
65.9 65.9 - Data.Data.Lens hitTest.\ (35)
65.9 65.9 - Data.Data.Lens readCacheFollower (30)
65.9 65.9 - Data.Data.Lens readCacheFollower.\ (30)
65.9 65.9 - Data.Data.Lens insertHitMap (1)
65.9 65.9 - Data.Data.Lens insertHitMap.populate (1)
65.9 65.9 56.4 Data.Data.Lens insertHitMap.populate.f (1824891)
2.3 2.3 2.3 Data.HashMap.Base clone16 (2682671)
2.1 2.1 2.1 Data.HashMap.Base hash (6204631)
1.7 1.7 .4 Data.HashMap.Array copy (1620382)
1.3 1.3 1.3 Data.HashMap.Array copy.\ (1620382)
1.1 1.1 1.1 Data.Data.Lens insertHitMap.populate.fs (2189870)
.9 .9 .9 Bound.Var gfoldl (364976)
.5 .5 .5 Data.HashMap.Array new_ (810191)
.5 .5 .5 Bound.Var gunfold (364976)
.3 .3 .3 Data.HashMap.Base sparseIndex (3620621)
.2 .2 .2 Bound.Scope gfoldl (182489)
堆配置文件:
我只想回答这个问题:这是一个错误,dfeuer reported it to ekmett/lens
。
同时使用 tinplate
代替 uniplate
是一个可行的解决方法。
使用最新版本的 Bound
和 Control.Lens.Plated
,以下 transform
调用会导致程序无限循环并愉快地消耗我的 RAM。有趣地终止程序会导致打印正确的结果,尽管我不知道为什么。
我已将问题追溯到 Scope
数据类型。删除它会使程序按预期运行。
使用 ./program +RTS -p -h
进行分析显示 Data.Data.Lens.insertHitMap.populate
是有问题的部分。附上一些分析。
这是官方解决方法的预期行为还是可能是错误?
我正在使用 GHC 版本 8.0.2,除 bound-2
之外的所有包都是堆栈 lts-8.17
的一部分。该程序被编译为 ghc test.hs
。启用或禁用优化不会影响问题。
因为我怀疑这是一个错误,所以我在 ekmett
的 bound
存储库(用于交叉引用目的)上为此打开了一个 issue。
-- file: test.hs
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable,
DeriveDataTypeable #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
module Main (main) where
import Bound
import Control.Lens hiding (List)
import Control.Lens.Plated
import Data.Deriving (deriveShow1, deriveEq1)
import Data.Data
import Data.Data.Lens (uniplate)
data Expr a = Var a
| List [Expr a]
| Apply (Expr a) (Expr a)
| Lam (Scope () Expr a)
| Nop
deriving (Functor, Foldable, Traversable, Data)
main = do
print ex
print $ transform removeTest ex
ex :: Expr String
ex = List [Apply (Var "test") $ List [Var "arg1", Var "arg2"]
,Apply (Var "two") (Var "three")]
removeTest :: Expr String -> Expr String
removeTest = \expr -> case expr of
Apply (Var "test") _ -> Nop
_ -> expr
instance Data a => Plated (Expr a) where
plate = uniplate
makeLenses ''Expr
makeBound ''Expr
deriveEq1 ''Expr
deriveShow1 ''Expr
deriving instance Show a => Show (Expr a)
deriving instance Eq a => Eq (Expr a)
输出:
List [Apply (Var "test") (List [Var "arg1",Var "arg2"])
,Apply (Var "two") (Var "three")]
^CList [Nop,Apply (Var "two") (Var "three")]
-- profiterole stats
TOT INH IND
99.9 99.9 .1 MAIN MAIN (0)
99.9 99.9 .1 MAIN MAIN (0)
99.9 99.9 34.0 Main CAF (0)
65.9 65.9 - Data.Data.Lens fromOracle (35)
65.9 65.9 - Data.Data.Lens hitTest (0)
65.9 65.9 - Data.Data.Lens hitTest.\ (35)
65.9 65.9 - Data.Data.Lens readCacheFollower (30)
65.9 65.9 - Data.Data.Lens readCacheFollower.\ (30)
65.9 65.9 - Data.Data.Lens insertHitMap (1)
65.9 65.9 - Data.Data.Lens insertHitMap.populate (1)
65.9 65.9 56.4 Data.Data.Lens insertHitMap.populate.f (1824891)
2.3 2.3 2.3 Data.HashMap.Base clone16 (2682671)
2.1 2.1 2.1 Data.HashMap.Base hash (6204631)
1.7 1.7 .4 Data.HashMap.Array copy (1620382)
1.3 1.3 1.3 Data.HashMap.Array copy.\ (1620382)
1.1 1.1 1.1 Data.Data.Lens insertHitMap.populate.fs (2189870)
.9 .9 .9 Bound.Var gfoldl (364976)
.5 .5 .5 Data.HashMap.Array new_ (810191)
.5 .5 .5 Bound.Var gunfold (364976)
.3 .3 .3 Data.HashMap.Base sparseIndex (3620621)
.2 .2 .2 Bound.Scope gfoldl (182489)
堆配置文件:
我只想回答这个问题:这是一个错误,dfeuer reported it to ekmett/lens
。
同时使用 tinplate
代替 uniplate
是一个可行的解决方法。