回调如何修改纯函数式编程中的对象状态?

时间:2014-01-14 16:13:21

标签: callback functional-programming

问题在于:GUI按钮有一个回调函数,可以将其状态从选中切换为未选中状态。

在命令式编程语言中,它很容易实现:只需修改Button的状态即可。例如:

void callback(Button btn) {
    btn.setChecked(!btn.getChecked());
}

但是在纯函数式编程中,回调不能改变对象的状态。回调唯一能做的就是创建一个具有新状态的新Button对象。例如:

Button callback(Button btn) {
    return new Button(!btn.checked);
}

上述回调创建的按钮不会成为程序GUI的一部分,因为外部函数必须获取回调结果并将新按钮值重新集成到GUI中。

此外,按钮不应具有上述类型签名的回调,因为按钮回调应该是通用的。即回调的类型签名是:

Object callback(Object object);

我在纯函数代码中可以想到的唯一解决方案是回调接受并返回全局GUI,例如:

GUI callback(GUI gui, Button btn) {
    ...bla bla bla recreate the gui tre ...
}

那么我如何在纯功能代码中执行此操作?我的纯函数回调如何改变我按钮的状态?

2 个答案:

答案 0 :(得分:2)

以纯粹的功能方式设计GUI的最优雅方式可能是Functional Reactive Programming - 另请参阅this SO questionHaskellWiki page

如果你这样做,那么你本身就不会使用回调,而是定义解释“行为”应该随着时间和用户输入而演变的函数。点击按钮将是一个影响相关行为的“事件”。

如果你想坚持使用更传统的回调模式,那么我认为必须采取一定程度的强制行为。

但是,您可以将可变性的数量保持在最低限度,例如只有一个顶级可变值来表示程序的整个当前状态,可能与您上面提到的GUI类型有些相似。该值将是一些复杂的代数数据类型,它包含可以更改的所有内容。

您还可以使用约束访问该顶级状态的抽象,例如通过限制只访问它的特定部分,只允许访问特定回调的抽象。

答案 1 :(得分:0)

简短回答:他们(回调)不能。不要试图将命令式的风格拉到功能性世界 可能的解决方案是:

  1. 您创建一个新按钮并将其重新集成到您的GUI中(如您所述)。大多数功能GUI框架实际上都是这样的。
  2. 您的按钮变为无限懒惰的状态流,其中事件请求新状态。实际上,这也是反应式编程的一个实例(我知道你已经阅读了维基百科,但有时候关于维基百科的文章是不够的。)在这种情况下,你的“回调”是一个获得新状态和准备的函数“下一个”。