用小控件编程

托马斯·哈格伦和马格努斯·卡尔森

查尔默斯理工大学计算科学,
S-412 96哥德堡,瑞典。
电子邮件:hallgren,magnus@cs.chalmers.se

1.简介

在这些笔记中,我们介绍了福吉特图书馆及其背后的思想主要是一个用于在高层上构建图形用户界面(GUI)的工具包惰性函数语言Haskell中的抽象级别,但它也允许您构建通过Internet与其他程序通信的程序。

除了描述如何使用Fudget Library之外,我们还试图描述其底层以读者能够在自己喜欢的地方使用的方式函数语言。

Fudget库的设计始于寻找GUI的良好抽象构建块,即利用强大抽象机制的抽象在函数语言中发现(高阶函数、多态性等),因此,希望它比传统GUI工具箱中的抽象更好,命令式语言。我们认为,如果抽象简化了编程,例如,通过使程序更简洁,从而更容易编写、阅读和维护。

另一个需要考虑的是,在当今的编程语言实现中,效率和高抽象级别之间通常存在冲突,因此抽象是一种能够合理高效实现的抽象。如果我们不能我们已经与现实世界失去了联系。总结如下:

重要的是不要与现实世界失去联系,但这并不意味着一个必须明确地在世界各地传递。
Fudget库中使用的主要抽象是软糖.fudget是一个过程可以通过消息传递与其他并发运行的fudget通信,并与外部世界。fudget是反映消息类型的一类值fudget发送和接收。这使得通信类型安全。软糖可能有一个内部状态,在fudget类型中不可见。中的控件编程这方面类似于面向对象编程,其中状态信息是分布式的并隐藏在对象中,而不是集中化,并暴露于任意使用或误用。但是,状态信息的封装也使得伪造的东西很容易编写,比如函数语言中的函数。

控件在流处理器,一种更简单的过程通过输入流和输出流的值与周围环境进行通信。

1.1概述

我们首先简要介绍函数式语言中的一些常见I/O方法(第2节)。在这些方法中,您可以指定I/O操作的单线程序列,因此实际的功能程序采用顺序命令程序的形式顶级。

对于反应式编程(第2.3节),更具吸引力的程序结构是一组并发进程,所以我们引入流处理器(第3节)。流处理器是使用输入流并产生输出流的过程。组合器串行组合、并行组合和循环允许程序被构造为网络流处理器。流处理器可以纯功能编程。

除了在网络中与邻居通信外,在反应式编程中上下文许多流处理器也需要与外部实体通信通过I/O系统。因此,我们介绍软糖(第4节),流处理器除了与其他系统通信的流之外,还可以访问I/O系统流处理器或软糖。反应式程序可以被构建为一个伪造的网络。

fudgets的主要用途是构建图形用户界面(GUI)。这个GUI中的构建块(按钮、菜单、滑块等)让人联想到物理设备因为它们是或多或少独立和并行操作的独立单元。因此,反应式编程模型对于GUI来说非常自然。在Fudget库中,GUI元素表示为fudgets。复杂的用户界面是通过组合虚设来构建的表示GUI元素和其他流处理器(第5节)。

使用fudget设计GUI程序有两个方面:计算方面和视觉方面。软糖系统允许你一次一次地担心它们时间。由于有了自动布局系统,您可以专注于计算在初始开发阶段。您可以稍后向程序添加布局信息,如果默认布局不够(第5.5节)。

在设计软件库(例如GUI工具包)时,通常在通用性和简单性。通用性通常通过使用许多参数来实现。拥有为许多参数提供值显然会使库组件更加难以使用。在一些编程语言中,有一种机制允许函数参数如果函数定义为其指定了默认值,则省略。这将使函数易于使用,同时可定制。我们使用的语言(Haskell)没有有这样的机制,但fudget库中使用的方案非常接近。它使用Haskell的类型类系统,以避免名称的扩散(第5.6节)。

我们所讨论的第二种假的用法是构建基于网络的客户机/服务器程序。典型的服务器必须能够处理来自多个同步客户端,因此使用处理程序进程(即处理程序)构造服务器很有用fudget)。用Haskell编写的带有fudget库的程序可以进行通信使用其他语言编写的程序,但对于所有程序我们展示了一种简单的方法来确保通信是类型安全的(第6节)。

1.2第一个示例

作为使用Fudget Library构建图形用户界面的预览,图1显示了一个小程序:一个简单的计数器。用户界面包含一个按钮和一个数字显示。按下按钮时,显示屏中的数字将递增。

该程序的核心是计数器F,其中两个fudgets实现两个用户界面元素和实现点击计数器的流处理器是使用串行复合运算符连接>==<。数据从右向左流动。这个按钮输出馈送到计数器的点击。每次单击时,计数器都会增加其内部整数状态,并将新值输出到显示器。

对GUI构建感兴趣的读者可以直接跳到第5节然后回到前面的部分,了解更多关于流处理器和真的是软糖。

模块Main(Main)其中--一个简单计数器进口Fudgetsmain::对话main=fudlogue(shellF“计数器”counterF)计数器F=intDispF>==<absF countSP>==<incButtonFinc按钮F::F点击点击incButtonF=buttonF“增量”countSP::SP点击IntcountSP=putSP启动状态$mapAccumlSP inc启动状态其中inc n单击=(n+1,n+1)启动状态=0
图1。反例


完整的论文可用
[Fudgets主页]