有没有办法确保某些特定类型的对象(基本上ForeignPtr
)非常积极地进行垃圾收集?我有这样一种简单的类型:
data SomePtr = SomePtr { ptr :: ForeignPtr CUChar, size :: CSize }
alloc :: CSize -> IO SomePtr
free :: SomePtr -> IO ()
free = finalizeForeignPtr . ptr
Run Code Online (Sandbox Code Playgroud)
我认为标准理论是引用计数(我自己也会这样做,比方说,C++)比ghc使用的GC慢,这就是为什么它不使用它.但对我来说问题是,当使用外部分配的对象(如GPU内存)时,最终释放它的承诺是不够的.内存非常稀缺,据我所知,ForeignPtr
终结器实际上并没有被调用.我想尽快释放记忆,所以我最终打电话给finalizeForeignPtr
自己.
是否有某种方法可以告诉ghc在破坏某些特定类型的对象时非常积极?
或者我是以错误的方式来做这件事的?
这是一个示例代码来说明我的意思:
{-# LANGUAGE RecordWildCards #-}
import Foreign.ForeignPtr.Safe
import Foreign.Ptr
import Foreign.Marshal.Alloc
import Foreign.Storable
import Control.Monad
import Foreign.C.Types
import Text.Printf
data FPtr = FPtr { fptr :: ForeignPtr CUChar, size :: CSize }
foreign import ccall "falloc" falloc …
Run Code Online (Sandbox Code Playgroud) 我试图在Haskell中实现一个简单的dp算法(这是来自Project Euler的Collatz猜想问题); 这是等效的c ++:
map<int,int> a;
int solve(int x) {
if (a.find(x) != a.end()) return a[x];
return a[x] = 1 + /* recursive call */;
}
Run Code Online (Sandbox Code Playgroud)
所以我在Haskell中编写的代码最终看起来像这样:
solve :: (Memo, Int) -> (Memo, Int)
solve (mem, x) =
case Map.lookup x mem of
Just l -> (mem, l)
Nothing -> let (mem', l') = {- recursive call -}
mem'' = Map.insert x (1+l') mem'
in (mem'', 1+l')
Run Code Online (Sandbox Code Playgroud)
(我认为我只是在这里重新实现状态monad,但暂时不介意.)调用solve的代码尝试找到它最多可以为参数提供的最大值K = 1e6:
foldl'
(\(mem,ss) k ->
let (mem',x') = solve (mem, k) …
Run Code Online (Sandbox Code Playgroud) 假设我定义了一个类型
data A a = A a | B deriving Show
Run Code Online (Sandbox Code Playgroud)
我知道这(B :: A Int) == (B :: A Double)
不是类型检查,因为A Int
它A Double
是不同的,不相等的类型,所以我不能申请(==) :: Eq a => a -> a -> Bool
但后来我可以问ghci是什么show B
,而ghci说它是字符串"B".究竟是什么类型的B
?是A Int
吗?为什么?为什么ghci不抱怨这种类型B
是模棱两可的,因为它可以A a
绝对任意a
.
我同样可以问ghci是什么show (B==B)
,它说"真",这两者的类型B
是什么?
当我向ghci询问B的类型时:t B
,会打印出来B :: A a
,但除非我在上面的两个例子中感到困惑,否则它必须是一些没有任何类型参数的特定类型.那么如何找出B
in 的类型B==B
呢?
我有点困惑.这在任何地方描述?