假设我们有一个功能
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应对这项任务的方式?
感谢。
答案 0 :(得分:3)
让我们从清理变化开始变得更加清晰
change sd f input = if input then func input else sd
所以当我们撰写这些
时change d1 $ change d2 $ change d3
GHC首先为每个人存储一个thunk。请记住,$
是一个函数,因此整个change d*
事物最初将成为一个thunk。 Thunks相对便宜,如果你不是马上创造10k左右,你就可以了:)所以不用担心。
现在的问题是,当你开始评估时会发生什么,答案是,它仍然不会评估复杂的数据,因此它仍然具有很高的内存效率,而且只需要强制input
来确定分支它正在采取。因此,在选择运行并向您返回一个之前,您永远不应该实际完全评估SophisticatedData
,如果您使用它,它将被评估为需要。
此外,在每一步中,GHC都可以垃圾收集不需要的thunk,因为它们不再被引用。
总之,你应该没问题。相信懒惰
答案 1 :(得分:1)
你是对的:如果foo
是对change
的O(n)个调用链,那么每次调用foo
都会有O(n)开销。处理此问题的方法是记住foo
:
memoize :: Func -> Func
memoize f = \x -> if x then fTrue else fFalse where
fTrue = f True
fFalse = f False