首页 > 解决方案 > 部分应用函数的共享

问题描述

我目前正在尝试共享部分应用的功能。为了让分享可见,我使用了描摹效果。为了说明我的问题,我先展示一个简化的例子

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 函数中没有共享感兴趣。

标签: haskelllambdamonadssharing

解决方案


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

有些应用程序您真的不想共享。经典的例子是,如果要共享的值是一个惰性(可能是无限的)列表。那么在非共享的情况下,第一个使用站点可能会以流的方式处理这个列表,垃圾收集器可以在它之后立即清理。然后列表的第二个用户将需要重新进行列表构建计算,是的,但是一切都发生在O (1) 内存中。

通过共享,在这种情况下,您会保留对列表根目录的引用,因此垃圾收集器只会在第二个用户也使用该列表后才会启动。也许这发生在很久以后,在第一个用户已经将列表扩展到几 GB 之后。一般来说,你不希望这样!因此,lambdas (CAFs) 提供了一种在这种情况下防止共享的方法。只有当编译器确定共享在某些情况下确实有益时,它才会优化共享。

单子实例的单子计算共享是否State可能?

Y...是的,但我真的不明白你想分享什么以及如何分享。请澄清问题。


推荐阅读