我最近进入了函数式编程,并且学习了几种以引用透明的方式处理某些副作用的方法:
但是现在大多数“真实世界”的应用程序都与外部系统(如 Web 服务、数据库等)交互,这些系统可以由多个用户同时修改,它们有状态、长时间运行的操作等。所以情况并不那么简单如上述类别:向系统询问实体的状态或试图控制它的结果取决于其状态。此外,交互性也是一个要求:有一些用户可以任意点击的 GUI,也许我们还必须自动对来自系统的变化做出反应。
通过最大化纯函数的好处来设计和实现此类应用程序的模式是什么?或者上面的一些方法可以以我没有想到的方式应用于这个问题吗?该语言(例如 Java 或 Scala)不会强制执行 100% 纯度,因此我对由实践经验支持的实用解决方案感兴趣。
functional-programming architectural-patterns referential-transparency
如何在IO函数中使用纯函数?: - /
例如:我正在读取一个文件(IO函数),我想通过使用具有引用透明性的纯函数来解析其上下文,一个字符串.
似乎这样的世界,纯函数和IO函数是分开的.我怎么可能桥接他们?
在Haskell中,我有一个容器,如:
data Container a = Container { length :: Int, buffer :: Unboxed.Vector (Int,a) }
Run Code Online (Sandbox Code Playgroud)
这个容器是一棵扁平的树.它的访问器通过向量(!)执行二进制(log(N))搜索,以便找到index存储的正确存储桶.
(!) :: Container a -> Int -> a
container ! index = ... binary search ...
Run Code Online (Sandbox Code Playgroud)
由于连续访问可能位于同一个存储桶中,因此可以通过以下方式进行优化:
if `index` is on the the last accessed bucket, skip the search
Run Code Online (Sandbox Code Playgroud)
棘手的一点是这last accessed bucket部分.在JavaScript中,我只是不明确地修改容器对象上的隐藏变量.
function read(index,object){
var lastBucket = object.__lastBucket;
// if the last bucket contains index, no need to search
if (contains(object, lastBucket, index))
var bucket = …Run Code Online (Sandbox Code Playgroud) optimization haskell functional-programming referential-transparency
因此,我正在尝试学习FP,而我正试图了解参考透明度和副作用.
我已经了解到在类型系统中明确显示所有效果是保证参照透明度的唯一方法:
"主要是功能性编程"的想法是不可行的.通过仅部分消除隐含的副作用,使命令式编程语言更安全是不可能的.留下一种效果通常足以模拟你刚试图去除的效果.另一方面,允许在纯语言中"忘记"效果也会以自己的方式造成混乱.
不幸的是,没有黄金中间,我们面临着一个经典的二分法:排除中间的诅咒,它提出了(a)尝试使用纯度注释来驯服效果的选择,但完全接受了你的代码是仍然从根本上有效; 或者(b)通过在类型系统中明确表达所有效果并务实地完全接受纯度 - 来源
我还了解到,像Scala或F#这样的非纯FP语言不能保证引用透明性:
强制执行引用透明性的能力与Scala的目标是非常不兼容,即具有可与Java互操作的类/对象系统.- 来源
在非纯FP中,程序员需要确保参考透明度:
在ML,Scala或F#等不纯语言中,程序员需要确保引用透明性,当然在动态类型语言(如Clojure或Scheme)中,没有静态类型系统来强制引用透明性.- 来源
我对F#很感兴趣,因为我有.Net背景所以我的下一个问题是:
如果F#编译器没有强制执行F#应用程序,我该怎么做才能保证引用透明性?
f# functional-programming side-effects referential-transparency
让我们说在我的纯Scala程序中,我依赖于Java服务.此Java服务接受侦听器在某些数据更改时通知我.
假设数据是一个元组(x,y),只要X或Y发生变化,java服务就会调用监听器,但我只对X感兴趣.
为此,我的监听器必须保存X的最后一个值,并仅在oldX!= X时转发更新/调用,所以为了使我的不纯scala监听器实现必须保存var oldX
val listener = new JavaServiceListener() {
var oldX;
def updated(val x, val y): Unit = {
if (oldX != x) {
oldX = x
//do stuff
}
}
javaService.register(listener)
Run Code Online (Sandbox Code Playgroud)
如何在没有val或可变集合的情况下为Scala设计这种东西的包装器?我不能在JavaServiceListener级别,因为我受到方法签名的约束,所以我需要另一个层,在这个层之上,java监听器以某种方式转发
functional-programming scala referential-transparency purely-functional
什么是局部推理?它与参照透明度、等式推理和惰性有何关系?
functional-programming side-effects referential-transparency
是否有可能在Haskell(使用RANDOM-PIVOT)中实现一个仍然具有简单Ord a => [a]->[a]签名的快速排序?
我开始理解Monads了,而且,就像现在一样,我将monad解释为像'命令模式'这样的东西,这对于IO非常有用.
所以,我理解一个返回随机数的函数实际上应该返回一个像IO一样的monadic值,因为否则会破坏引用透明性.我也明白,应该没有办法从返回的monadic值中"提取"随机整数,否则,它会再次破坏参照透明度.
但是,我仍然认为应该可以实现'纯' [a]->[a]快速排序功能,即使它使用随机数据透视,因为它是参考透明的.从我的角度来看,随机数据透视只是一个实现细节,不应该改变函数的签名
OBS:我对具体的快速排序问题实际上并不感兴趣(所以,我不想听起来很粗鲁,但我不是在寻找"使用mergesort"或"随机支点不会在实践中提高性能"的答案)我实际上对如何实现一个在其中使用'不纯'函数的'纯'函数感兴趣,在快速排序的情况下,我可以确保该函数实际上是纯函数.
Quicksort就是一个很好的例子.
Edison API和Core模块是纯功能数据结构的Haskell实现
F#和原生.Net数据结构是否足以涵盖Edison API和Core中的用例?
尝试将API和CORE Haskell模块移植到F#会有什么好处吗?
f# haskell immutability referential-transparency data-structures
我只是想知道如何使用纯函数式语言连接API而不引入副作用?
是否有算法实现纯功能集?
预期的操作是联合,交集,差异,元素?,空吗?和邻接.
这些并不是硬性要求,我很乐意学习一种只实现其子集的算法.
algorithm functional-programming set referential-transparency data-structures
haskell ×4
f# ×2
side-effects ×2
algorithm ×1
api ×1
immutability ×1
io ×1
monads ×1
optimization ×1
quicksort ×1
random ×1
scala ×1
set ×1