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



问题是:GUI按钮有一个回调,可以将其状态从选中切换到未选中。

在命令式编程语言中,实现起来非常简单:只需修改按钮的状态即可。例如:

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 ...
}

那么,我该如何在纯函数代码中做到这一点呢?我的纯功能回调如何更改按钮的状态?

以纯功能的方式设计GUI最优雅的方法可能是功能反应式编程-另请参阅这个SO问题和HaskellWiki页面。

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

如果你想坚持使用更传统的回调模型,那么我认为一定程度的命令行为是必要的。

然而,您可以通过例如只具有一个表示程序的整个当前状态的顶级可变值来将可变性保持在最低限度,这可能与您上面建议的GUI类型有些相似。该值将是某种复杂的代数数据类型,包含所有可能更改的内容。

您还可以使用限制对该顶级状态的访问的抽象,例如,通过仅限制对其特定部分的访问,并仅将对这些抽象的访问权限授予特定回调。

简单回答:他们(回调)不能。不要试图把命令式风格拉到实用的世界里
可能的解决方案有:

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

最新更新