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)
那么我如何在纯功能代码中执行此操作?我的纯函数回调如何改变我按钮的状态?
也许以纯函数方式设计 GUI 的最优雅的方法是函数响应式编程- 另请参阅此 SO 问题和HaskellWiki 页面。
如果您这样做,那么您本身就不会使用回调,而是定义函数来解释“行为”应如何随着时间和用户输入而演变。单击按钮将是一个会影响相关行为的“事件”。
如果您想坚持使用更传统的回调模型,那么我认为某种程度的命令式行为是必要的。
但是,您可以通过例如仅使用一个表示程序的整个当前状态的顶级可变值(可能与您上面建议的类型有些相似)来将可变性保持在最低限度GUI。该值将是某种复杂的代数数据类型,其中包含可以更改的所有内容。
您还可以使用抽象来限制对顶级状态的访问,例如,通过限制仅访问其特定部分,并仅向特定回调提供对这些抽象的访问。