2013-10-21 94 views
0
功能的

让假设我们有一个函数性能改变功能

type Func = Bool -> SophisticatedData 
fun1 :: Func 

,我们想改变这个功能的一些输入:右

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

我是那之后的几个电话changeendFunc = change data1 $ change data2 $ startFunc)生成的函数会每次调用所有中间函数?我是否确定GC无法删除未使用的数据?什么是Haskell的方式来应对这项任务?

谢谢。

+1

随着GHC,你甚至不会计算数据,直到它的需要(懒洋洋),或者如果您已被迫评价GC应该能够清理之后没有更多的参考资料。 – bheklilr

+2

附注:'data'是关键字,不能用作变量名称。 –

回答

3

那么让我们来通过清理变化多一点清晰

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

因此,开始的时候,我们通过存储为他们每个人一个thunk撰写这些

change d1 $ change d2 $ change d3 

GHC开始。请记住$是一个函数,因此整个change d*事情一开始就会变成一个thunk。 Thunk相对便宜,如果你一次不创建10k左右的话,你就会很好:)所以不用担心。

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

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

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

+0

所以,如果我有'$'s的O(n),每次调用这个函数都是O(n)? – ElectricHedgehog

+0

@ElectricHedgehog空间还是速度? – jozefg

+0

速度。我认为所有呼叫的空间总数都是O(n)。 – ElectricHedgehog

1

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

memoize :: Func -> Func 
memoize f = \x -> if x then fTrue else fFalse where 
    fTrue = f True 
    fFalse = f False 
+0

你说得对,但你应该在'fTrue = f $!中添加'$!'运算符! TRUE'。在另一种情况下,评估将是懒惰的,而且每次都会计算'memoize'函数。 – ElectricHedgehog

+0

@ElectricHedgehog您声称'fTrue'会是懒惰的,但您声称memoized函数每次都会产生O(n)代价是错误的。自己测试! –