共享部分应用的功能

我目前正在尝试共享部分应用的功能。为了使共享可见,我使用了跟踪效果。为了说明我的问题,我首先显示一个simplified example

f1,f2,f3,f4 :: Int -> Int
f1   = \x -> trace "f1" 0 + x
f2 x = trace "f2" 0 + x
f3   = (trace "f3" 0 +)
f4   = (+) (trace "f4" 0)

在以下情况下,我比较了这些功能,其中f1被不同的功能代替。

apply :: (Int -> Int) -> (Int -> Int) -> Int
apply f g = f 42 + g 42

result = let f = f1
         in apply f f

输出(未经优化编译)如下。

f1 f1 f2 f2 f3 f4 336

核心代码显示f1f2都是lambda函数,而f3f4是部分应用的函数。在第一种情况下,lambda主体中似乎没有共享参数,而在第二种情况下有效。启用编译器优化会导致所有定义都共享,但是我对为何lambda函数中不存在共享感兴趣。

wr5279 回答:共享部分应用的功能

  

我对为什么lambda函数中没有共享感兴趣。

在某些应用中,您确实想要共享。经典的例子是,如果要共享的值是一个懒惰(也许是无限)列表。然后,在非共享情况下,首次使用站点可以以流方式处理此列表,并且垃圾收集器可以在此之后立即进行清理。然后,列表的第二个用户将需要重新执行列表构建计算,是的,但是所有事情都发生在 O (1)内存中。

使用共享,在这种情况下,您将保留对列表根目录的引用,因此垃圾收集器仅在第二个用户也使用了列表之后才启动。在第一个用户将列表扩展到几GB大小之后,可能会在以后发生。一般来说,您不想要那样!因此,lambda(CAF)提供了一种在这种情况下防止共享的方法。只有在编译器确定共享确实在某些情况下是有益的情况下,它才会对共享进行优化。

  

是否完全可以为State之类的monad实例共享monadic计算?

是...是的,但是我不太了解您想分享什么以及如何分享。请澄清问题。

本文链接:https://www.f2er.com/2940222.html

大家都在问