sho*_*sti 398 user-interface f# haskell functional-programming
我最近发现了FP bug(试图学习Haskell),到目前为止我已经看到了(一流的功能,懒惰的评估和所有其他好东西).我还不是专家,但是我已经开始发现在功能上比在基本算法上强制推理更容易(而且我很难回到我必须去的地方).
然而,当前FP看起来平坦的一个领域是GUI编程.Haskell方法似乎只是包装命令式GUI工具包(例如GTK +或wxWidgets)并使用"do"块来模拟命令式样式.我没有使用过F#,但我的理解是它使用OOP和.NET类做了类似的事情.显然,有一个很好的理由 - 当前的GUI编程完全是关于IO和副作用的,所以对于大多数当前的框架来说,纯函数式编程是不可能的.
我的问题是,是否可以使用GUI编程的功能方法?我无法想象在实践中这会是什么样子.有没有人知道任何尝试此类事物的框架(实验或其他)(或者甚至是为功能语言设计的任何框架)?或者只是使用混合方法的解决方案,其中OOP用于GUI部件,FP用于逻辑?(我只是想出于好奇心 - 我很想认为FP是"未来",但GUI编程似乎是一个非常大的漏洞.)
Don*_*art 183
Haskell方法似乎只是包装命令式GUI工具包(例如GTK +或wxWidgets)并使用"do"块来模拟命令式样式
这不是真正的"Haskell方法" - 这就是你最直接地通过命令式界面绑定到命令式GUI工具包的方式.Haskell碰巧有相当突出的绑定.
有几种中等成熟或更实验的纯功能/声明式GUI方法,主要是在Haskell中,主要使用功能性反应式编程.
一些例子是:
对于那些不熟悉Haskell的人,Flapjax,http://www.flapjax-lang.org/ 是基于JavaScript的功能性反应式编程的实现.
Edw*_*ETT 74
我的问题是,是否可以使用GUI编程的功能方法?
您正在寻找的关键词是"功能反应式编程"(FRP).
Conal Elliott和其他一些人试图找到适合FRP的抽象方法,从而成为一个小屋行业.Haskell中有几种FRP概念的实现.
您可以考虑从Conal最新的"Push-Pull功能反应式编程"论文开始,但还有其他一些(较旧的)实现,其中一些来自haskell.org网站.Conal有覆盖整个领域的诀窍,他的论文可以在不参考之前的内容的情况下阅读.
要获得这种方法如何可以用于GUI开发的感觉,你可能想看看Fudgets,这虽然是有点长的牙齿,这些天,被设计在90年代中期,并呈现出坚实的FRP方法到GUI设计.
Tom*_*cek 62
Windows Presentation Foundation证明了功能方法在GUI编程中非常有效.它有许多功能方面和"好"的WPF代码(搜索MVVM模式)强调功能方法超过命令.我可以勇敢地声称WPF是最成功的真实功能GUI工具包:-)
WPF描述了XAML中的用户界面(虽然您可以将其重写为功能上看起来也是C#或F#),因此要创建一些用户界面,您可以编写:
<!-- Declarative user interface in WPF and XAML -->
<Canvas Background="Black">
<Ellipse x:Name="greenEllipse" Width="75" Height="75"
Canvas.Left="0" Canvas.Top="0" Fill="LightGreen" />
</Canvas>
Run Code Online (Sandbox Code Playgroud)
此外,WPF还允许您使用另一组声明性标记以声明方式描述动画和对事件的反应(同样,可以将其写为C#/ F#代码):
<DoubleAnimation
Storyboard.TargetName="greenEllipse"
Storyboard.TargetProperty="(Canvas.Left)"
From="0.0" To="100.0" Duration="0:0:5" />
Run Code Online (Sandbox Code Playgroud)
事实上,我认为,WPF有许多共同之处与Haskell的FRP(虽然我相信WPF设计师不知道玻璃钢,这是一个有点可惜 - WPF有时感觉有点怪异和不明确的,如果你正在使用的功能观点看法).
Tom*_*cek 28
我实际上会说功能编程(F#)是比C#更好的用户界面编程工具.你只需要稍微考虑一下这个问题.
我在第16章的函数式编程书中讨论了这个主题,但是有一个免费的摘录,它显示了(恕我直言)你可以在F#中使用的最有趣的模式.假设您要实现矩形绘图(用户按下按钮,移动鼠标并释放按钮).在F#中,您可以编写如下内容:
let rec drawingLoop(clr, from) = async {
// Wait for the first MouseMove occurrence
let! move = Async.AwaitObservable(form.MouseMove)
if (move.Button &&& MouseButtons.Left) = MouseButtons.Left then
// Refresh the window & continue looping
drawRectangle(clr, from, (move.X, move.Y))
return! drawingLoop(clr, from)
else
// Return the end position of rectangle
return (move.X, move.Y) }
let waitingLoop() = async {
while true do
// Wait until the user starts drawing next rectangle
let! down = Async.AwaitObservable(form.MouseDown)
let downPos = (down.X, down.Y)
if (down.Button &&& MouseButtons.Left) = MouseButtons.Left then
// Wait for the end point of the rectangle
let! upPos = drawingLoop(Color.IndianRed, downPos)
do printfn "Drawn rectangle (%A, %A)" downPos upPos }
Run Code Online (Sandbox Code Playgroud)
这是一种非常迫切的方法(采用通常的实用F#风格),但它避免使用可变状态来存储当前绘图状态和存储初始位置.它可以变得更加实用,我写了一个图书馆,作为我的硕士论文的一部分,我的博客将在未来几天内提供.
功能反应式编程是一种功能更强大的方法,但我发现它更难使用,因为它依赖于非常先进的Haskell功能(例如箭头).然而,在很多情况下它非常优雅.它的局限性在于您无法轻松编码状态机(这是反应程序的有用心理模型).使用上面的F#技术非常容易.
Kev*_*Won 15
你可以看看Don Syme在F#上的系列,他演示了如何创建一个gui.以下链接是该系列的第三部分(您可以从那里链接到另外两个部分).
使用F#进行WPF开发将是一个非常有趣的GUI范例......
http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-3-of-3/
Bor*_*aut 12
功能反应式编程背后的一个令人心碎的想法是让事件处理功能产生对事件和下一个事件处理功能的两种反应.因此,演进系统被表示为一系列事件处理功能.
对我来说,学习Yampa成为了正确实现功能生产功能的关键.有一些关于Yampa的好文章.我推荐The Yampa Arcade:
http://www.cs.nott.ac.uk/~nhn/Talks/HW2003-YampaArcade.pdf (幻灯片,PDF) http://www.cs.nott.ac.uk/~nhn/Publications/hw2003. pdf(全文,PDF)
在Haskell.org上有一个关于Yampa的维基页面
http://www.haskell.org/haskellwiki/Yampa
原Yampa主页:
http://www.haskell.org/yampa(遗憾的是此刻已被打破)
Elliot关于FRP的演讲可以在这里找到.
此外,不是一个真正的答案,而是一个评论和一些想法:不知何故,术语"功能GUI"似乎有点像矛盾(纯粹和IO在同一术语).
但我的模糊理解是,功能性GUI编程是关于声明性地定义时间相关函数,该函数采用(实际)时间相关的用户输入并产生时间相关的GUI输出.
换句话说,这个函数被声明地定义为微分方程,而不是强制使用可变状态的算法.
因此,在传统的FP中,使用时间无关的功能,而在FRP中,使用时间相关的功能作为用于描述程序的构建块.
让我们考虑模拟用户可以与之交互的弹簧上的球.球的位置是图形输出(在屏幕上),用户推球是按键(输入).
在FRP中描述这个模拟程序(根据我的理解)是通过单个微分方程(声明性地)来完成的:加速度*质量=弹簧拉伸*弹簧常数+用户施加的力.
这是一段关于ELM的视频,展示了这一观点.
自从第一次提出这个问题以来,功能性反应式编程已经成为Elm的主流.
我建议在http://elm-lang.org上查看它,它还有一些真正优秀的交互式教程,介绍如何制作功能齐全的浏览器内GUI.
它允许您创建功能完备的GUI,您需要自己提供的代码只包含纯函数.我个人发现它比各种Haskell GUI框架更容易进入.
截至2016年,还有几个相对成熟的Haskell FRP框架,如Sodium和Reflex(以及Netwire).
关于功能反应式编程的Manning书籍展示了Sodium的Java版本,用于工作示例,并说明了与命令式和基于Actor的方法相比,FRP GUI代码库的行为和扩展方式.
最近还有一篇关于Arrowized FRP的文章,以及在法律规定的纯FRP设置中加入副作用,IO和变异的前景:http://haskell.cs.yale.edu/wp-content/uploads/2015/10/ dwc-yale-formatted-dissertation.pdf.
另外值得注意的是,诸如ReactJS和Angular等许多其他JavaScript框架已经或正在朝着使用FRP或其他功能方法来实现可扩展和可组合的GUI组件.