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

axi*_*mar 7 functional-programming callback

问题出在这里:GUI按钮有一个回调,可以将其状态从选中切换到未选中状态.

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

void callback(Button btn) {
    btn.setChecked(!btn.getChecked());
}
Run Code Online (Sandbox Code Playgroud)

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

Button callback(Button btn) {
    return new Button(!btn.checked);
}
Run Code Online (Sandbox Code Playgroud)

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

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

Object callback(Object object);
Run Code Online (Sandbox Code Playgroud)

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

GUI callback(GUI gui, Button btn) {
    ...bla bla bla recreate the gui tre ...
}
Run Code Online (Sandbox Code Playgroud)

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

GS *_*ica 2

也许以纯函数方式设计 GUI 的最优雅的方法是函数响应式编程- 另请参阅此 SO 问题HaskellWiki 页面

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

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

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

您还可以使用抽象来限制对顶级状态的访问,例如,通过限制仅访问其特定部分,并仅向特定回调提供对这些抽象的访问。