Fudget解决方案
爆炸游戏是使用两个基本的棋盘组合子来实现的游戏。第一个组合词是图形按钮F::F类图纸点击data Drawing=。。。
创建包含可更改图形的按钮动态地。图形按钮F
用于实现棋盘上的方块。第二个组合词是
类型坐标=(Int,Int)boardF::坐标->(坐标->F类a b)->F类(协调,a)(协调,b)
它给出了电路板的尺寸和坐标的函数一个方块到一个fudget实现该方块创建一个并行用适当的布局组成方形软糖。广场软糖是用它们的坐标来寻址的。爆炸游戏的实现如下所示(评论如下):
爆炸板F=循环F(吸收F路线SP>==<boardF板尺寸boardSize atomsSquareF)哪里routeSP=…--8条线路atomsSquareF::坐标->F类AtomColor方形事件原子平方F(x,y)=循环通过右F(绝对频率cltrSP)原子按钮F哪里ctrlSP=…--18条线路原子按钮F::F类(NumberOfAtom、AtomColor)点击atomsButtonF=…--30行
评论:最后,
- 爆炸游戏可以从Fudget演示表单(此处称为原子).
- 在一个实现中还使用了棋盘游戏组合器比赛的关键奥赛罗,可以从以下位置进行测试演示表单。
(托马斯·哈格伦)
我们定义软糖组合锁F
,它需要组合作为字符串参数。软糖的类型相同(F类点击 点击
)作为按钮F
,这意味着我们可以使用组合锁F
无论在何处按钮F
已使用。
这是一个显示密码锁的程序。程序当按下正确的组合(123)时退出。
(托马斯·哈格伦)
fudget库有一个名为
滚动F::F a b->F a b
任何用户界面篡改都可以放在这样的容器中例如爆炸游戏。
(未实施。)Thomas Hallgren编写了一个WWW浏览器,具有以下功能:
- 接受大多数HTML 2.0(?)。
- 支持内联图像(格式:gif、jpeg、xbm、pnm)。
- 并行获取多个内联图像。
- 支持表单。
- 支持的协议:http、gopher、ftp、news、本地文件/目录。
- 易于剪切/粘贴URL。只需在任何X窗口中选择一个URL,然后按浏览器中的中间按钮。
关于实施:
- HTML输入被解析为抽象语法树,然后分几个阶段转换为绘图命令生成具有适当布局的文本,字体和其他属性。
- 表单元素和图像实现为在文本中适当放置的普通软糖。(它们的大小会影响布局。)
- 通过调用外部程序进行图像转换(giftopm等)。
- 抖动在Haskell中完成。
- 大小:4000行。时间:约1人月。
托马斯还没有创办自己的公司。。。这是一个正在运行的模拟。模拟窗口具有以下按钮:
- 运行
- 在此窗口中启动/停止模拟。
- 状态
- 显示与此仿真关联的状态窗口。
- 新建
- 创建新的仿真窗口。
- 关闭
- 关闭此模拟(以及相关状态窗口(如果存在)。如果是最后一次模拟程序退出。
- 退出
- 退出程序。
状态窗口显示存在两个模拟,第一个正在运行。的当前大小单元是10个像素。问题的答案
- 程序的动态行为是如何编程的?
该程序有两个动态功能:
- 模拟。生命窗口计算特定时间后的新世代时间间隔。这是用软糖编程的
计时器F::F(可能(Int,Int))勾选
当它收到消息时只是(i,0)
,将输出a勾选
每一个我
秒。
- 动态创建新的Life实例。这是用编程的
动态列表F
,它接受消息
(t,动态创建f)
- 生成新的软糖
(f)
,给它标签t吨
(t,DynMsg m)
- 发送消息
米
将标签改为fudgett吨
(t,动态)
- 杀死软糖已标记
t吨
- 每个生命游戏实例如何跟踪所有其他生命游戏?
答案是每个生命的实例不会“跟踪”其他实例。实例通过消息通信经过。消息使用数据类型进行编码生命事件
和LifeCommand公司
.每一条生命实例是一个接受生命事件
消息,并发送LifeCommand公司
消息。
数据类型生命事件
和LifeCommand公司
或多或少是直接的规范中的编码。事件对应于中的用户操作列表、按钮和输入字段:
类型Lno=Int数据生命事件=
新游戏|
- 打开一个新的“生活游戏”窗口。
CloseMe(关闭我)|
- 关闭自己,而不是退出程序。
全部退出|
- 关闭所有窗口,从而退出程序。
带到FrontEvt Lno|
- 通过从列表中选择一个“生活的游戏”窗口用户可以将窗口“放在前面”(任何合适的地方给定系统的屏幕管理)。
新大小单元格大小|
- 用新的刷新显示单元格大小。
计算Bool
- 开始/停止计算和渲染几代人的生活。
命令用于控制每个生命实例。在非分布式在环境中,我们还需要“将窗口前置”、“更改单元格大小”更新状态列表时:data LifeCommand=BringToFrontCmd|SetSize CellSize|生命状态[(Lno,String)]
- 如何实现局部变化具有全球影响的计划?(例如改变所有显示的生命细胞的大小导致所有生命游戏更改显示模式)。
`全球效应”也是通过信息传递实现的。在这种情况下消息将广播到所有实例。
- 问题程序(3)使用的方法是同步的还是异步?对于同步,我们指的是立即的影响. 对于异步,我们的意思是它需要不同的、任意的延迟这一改变将在所有生活游戏中生效。
由于(3)包含大量I/O(重画等),因此可能存在任意延迟(X-Windows基于客户端/服务器)。但通常情况下,变化是“即时的”,不管那意味着什么。
- 在分布式应用程序中转换此程序需要什么生命游戏在不同的机器上并行运行?
fudget库支持套接字通信和客户机/服务器编程。消息传递技术是(几乎)透明,因为程序可以被收发器fudget取代连接到另一个程序。(目前,功能不能不幸的是,在程序之间传递。)
这个主模块定义LifeCommand公司
和生命事件
和功能这就解决了他们的问题。(马格努斯·卡尔森)
(未实施。)(未实施。)(未实施。)这个挑战基本上是对工具箱。中使用的流处理器的当前实现Fudgets是纯功能性的,因此具有确定性。这意味着当一些流处理器正在计算输出时,输入是已排队。因此,如果流处理器进入无限循环。整个程序死锁。另一方面,使用确定性合并。在大多数情况下,最好程序可以对来自在接受下一个活动之前。
这种解决方案在HCI学校并不常见,相反,我会把它放进去PCI学校:程序员计算机交互.我的意思是编程GUI界面而不必考虑布局或外观还有感觉。我所做的是定义一类对话框项:类型DiaF a=F a a类DialogItem a其中对话框::DiaF a
带有实例声明实例DialogItem Int where对话框=条带输入SP>^^=<积分F实例DialogItem Bool其中的对话框=切换按钮F""
用于整数和布尔对话框项。此外,我们希望实例DialogItem字符串,其中dialog=?
但在哈斯克尔,我们不能使用字符串
在一个实例中宣言。我们通过添加一个额外的方法(授予文本
类)在DialogItem:类DialogItem a其中对话框::DiaF a对话框列表::DiaF[a]
和实例instance(DialogItem a)=>DialogItem[a]其中dialog=dialogList
现在,我们可以为字符添加一个实例,这使字符串能够工作根据需要:实例DialogItem Char,其中dialogList=stripInputSP>^^=<stringF
但这当然还不够。我们还想合并对话框项在形成对话时。我们使用产品和总和类型:instance(DialogItem a,DialogItems b)=>DialogItem(任意a b),其中dialog=vBoxF(对话框>+<对话框)instance(DialogItem a,DialogItemb)=>DialogItems(a,b)其中dialog=hBoxF(对话框>.<对话框)
在这里,我们对布局进行了任意选择。不同项目的选择具有垂直布局,而属于相同的选项水平放置。
现在,我们有足够的能力定义一个对话框,该对话框将值处理为复杂如
Int(字符串,布尔)
例如!下面是一个使用这种对话框的程序:main=fudlogue$shellF“T”$fdia::DiaF(Int(String,Bool))dia=对话框f=labLeftOfF“输出”(显示f'(setBorderWidth 0)>=^<显示)>==<直径>===<labLeftOfF“输入”(读取>^=<inputDoneSP>^^=<stringF)
(在这里,我们忽略了这样一个事实,即使用阅读
,因为如果我们输入一些东西,程序就会崩溃无法分析的。我们真的应该读取
.)
在顶部,它显示对话框输出的值。它也有底部的输入字段,用于更改对话框(因此也是顶部显示)。图中显示了单击切换按钮并输入文本后在它右侧的输入字段中显示“Hello”。 | |
我们还可以在整数输入字段中输入一个数字。注释输出如何变化。 |
|
最后,我们可以通过输入值。 | |
一些注意事项
- 我们得到的对话框由
迪亚
。通过改变这一点,我们可以获得完全不同的对话框。这是一个程序示例,其中类型决定行为,通过过载机制。这就是为什么面向PCI的解决方案:程序员有时对他们程序的功能,而不是GUI的布局。使用这个对话框
同学们,可以做实验和更改程序以更改GUI中的数据类型,而不必改变GUI代码。 - 无法为对话框项。如果我们考虑具有多个的类型类参数(如中所示高弗),我们可以添加属性键入类:
类DialogItem t a其中对话框::t->DiaF a对话框列表::t->DiaF[a]instance(DialogItem ta)=>DialogItemt[a]其中dialog=对话框列表实例(DialogItem t a,DialogItem u b)=>DialogItem(t,u)(任一a b)其中dialog=对话框2(>+<)vBoxFinstance(DialogItem ta,DialogItemu b)=>DialogItem(t,u)(a,b)其中dialog=对话框2(>.<)hBoxF对话框2cp(t,u)=p(对话框t`c`对话框u)实例DialogItem字符串字符,其中dialogList ls=标签ls$stripInputSP>^^=<stringF实例DialogItem字符串Int,其中对话框ls=标签ls$stripInputSP>^^=<intFlabel=labLeftOfF实例DialogItem字符串Bool,其中dialog ls=标签ls$toggleButtonF“”
下面是这样一个愚蠢的对话示例:
dia::DiaF(任意Int(字符串、布尔值))dia=对话框(“A number”,(“or A string”,“and A bool”)
(马格努斯·卡尔森)
图中显示了三种相反的观点。左边的两个视图是链接到同一计数器,该计数器由数字表示0
在标题栏中,而右视图是一个副本,有头衔的1
.计数器控制在与挑战相比``auto-increment-mode“”由切换按钮auto控制。它在计数器中激活0
,如黑点所示在切换按钮中。递增按钮用于手动递增计数器,与计时器的状态无关。该程序分为两部分,一部分用于计数,另一部分用于一个用于处理复制和链接操作。后者包含在内在软糖里多个F
:
多F::(s->F v s)->F s v->s->F a b
在表达式中多F状态_预算视图_预算初始状态
状态_预算
是一个可以保持一个状态(类型秒
). 每当用户需要一个新副本,则会在动态列表F
.请注意,状态fudget不需要有可视的外观。首先,将对初始状态(初始状态
)并推出。每个启动的状态fudget驻留在集体欺骗,以及至少一个看法.论点查看预算(_F)
用于创建视图。视图是用“复制”和“链接”按钮装饰,并用外壳F
它添加了带有组编号的标题栏。每当新链接要求,将在该组中推出一个新视图。来自状态fudget将广播给组中的所有视图。来自查看(类型为v(v)
)被反馈给州法院在小组中。
这里是的完整代码多个F
.
在Multiple Counter示例中,状态fudget包含一个计数器和计时器。视图控件是一个整数显示切换按钮。从状态虚设输出到视图具有类型
类型状态=(Int,Bool)
视图fudgets发送类型为的消息数据视图=增量|自动Bool
给州政府的软糖。这里是主要的程序.(马格努斯·卡尔森)