0

假设我们有一个函数

type Func = Bool -> SophisticatedData
fun1 :: Func

我们想改变这个函数一些输入:

change :: SophisticatedData -> Func -> Func
change data func = \input -> if input == False then data else func input

我是否正确,在多次调用change( endFunc = change data1 $ change data2 $ startFunc) 后,结果函数每次都会调用所有中间函数?我说 GC 不能删除未使用的数据是对的吗?处理这项任务的haskell方法是什么?

谢谢。

4

2 回答 2

3

好吧,让我们从清理更改开始,使其更易读

change sd f input = if input then func input else sd

所以当我们编写这些

change d1 $ change d2 $ change d3

GHC 首先为它们中的每一个存储一个 thunk。请记住,这$是一个函数,所以一开始整个change d*事情都会是一个重击。Thunks 相对便宜,如果您不立即创建 10k 左右,那么您会很好:) 所以不用担心。

现在的问题是,当你开始评估时会发生什么,答案是,它仍然不会评估复杂的数据,所以它仍然非常节省内存,它只需要强制input确定它正在采用哪个分支。因此,SophisticatedData在选择运行并返回一个给您之前,您永远不应该真正完全评估,然后如果您使用它,它将根据需要进行评估。

此外,在每一步,GHC 都可以垃圾收集不需要的 thunk,因为它们不能再被引用。

总之,你应该没问题。相信懒惰

于 2013-10-21T17:19:07.547 回答
1

你是对的:如果foo是对 的 O(n) 调用链,change每次调用都会有 O(n) 开销foo。处理这个问题的方法是 memoize foo

memoize :: Func -> Func
memoize f = \x -> if x then fTrue else fFalse where
    fTrue  = f True
    fFalse = f False
于 2013-10-21T20:51:46.847 回答