haskell - 部分应用函数的共享
问题描述
我目前正在尝试共享部分应用的功能。为了让分享可见,我使用了描摹效果。为了说明我的问题,我先展示一个简化的例子。
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
核心代码显示f1
和f2
都是 lambda 函数,而f3
和f4
是部分应用函数。在第一种情况下,在 lambda 的主体中似乎没有共享参数,而在第二种情况下它可以工作。启用编译器优化会导致所有定义的共享,但我对为什么 lambda 函数中没有共享感兴趣。
解决方案
我对为什么 lambda 函数中没有共享感兴趣。
有些应用程序您真的不想共享。经典的例子是,如果要共享的值是一个惰性(可能是无限的)列表。那么在非共享的情况下,第一个使用站点可能会以流的方式处理这个列表,垃圾收集器可以在它之后立即清理。然后列表的第二个用户将需要重新进行列表构建计算,是的,但是一切都发生在O (1) 内存中。
通过共享,在这种情况下,您会保留对列表根目录的引用,因此垃圾收集器只会在第二个用户也使用该列表后才会启动。也许这发生在很久以后,在第一个用户已经将列表扩展到几 GB 之后。一般来说,你不希望这样!因此,lambdas (CAFs) 提供了一种在这种情况下防止共享的方法。只有当编译器确定共享在某些情况下确实有益时,它才会优化共享。
单子实例的单子计算共享是否
State
可能?
Y...是的,但我真的不明白你想分享什么以及如何分享。请澄清问题。
推荐阅读
- c++ - C++ 如何使用 lambda 表达式来捕获之前的迭代值?
- python - 如何在 numba 中创建结构化标量列表?
- python - Windows cx_freeze 上的“AttributeError: 'NoneType' 对象没有属性写入”
- game-engine - 在 ECS(实体组件系统)中,组件管理器和系统有什么区别?
- google-apps-script - 在“https://script.google.com/macros/”访问 XMLHttpRequest - 已被 CORS 政策阻止
- javascript - 如何在firebase网站中获取数据库子项的唯一ID
- scala - Scala 并行执行
- javascript - 如何使用javascript隐藏滚动条而不影响正文宽度?
- mysql - 将同一数据库中不同表中的数量和金额相乘
- swift - 定时器完成块中的变量不更新