功能GUI编程是否可行?

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的功能性反应式编程的实现.

  • 我100%同意这一点.为了清楚起见:经常使用现有GUI工具包的原因是因为它们存在.接触它们的原因往往是必要和不纯的,因为工具包往往是必要的和不纯的.工具包往往是必要和不纯的原因是因为它们所依赖的操作系统往往是必要的和不纯的.然而,没有任何根本*要求*任何这些都是不纯的:这些工具包有功能绑定,有功能工具包,甚至还有功能操作系统. (44认同)
  • 请参阅Conal Elliott关于水果的论文,以深入描述该技术和决策:http://conal.net/papers/genuinely-functional-guis.pdf我一直在做这种风格的纯功能GUI编程几个月了.我喜欢它,它是命令式UI编程的意大利式地狱的一种令人愉快的缓解,在这方面似乎比大多数命令式编程更糟糕. (32认同)
  • 卢奇提到的论文似乎已经死了.但是,在Conal Elliott的网站上有一个工作链接:http://conal.net/papers/genuinely-functional-guis.pdf (23认同)
  • 这只是一个懒惰的问题.(坏双关语.) (16认同)
  • 有一天,所有GUI设计都将通过WYSIWYG实现,逻辑实现功能.这是我的预测. (10认同)
  • Jorg:听起来令人兴奋.你能给我一个功能操作系统的例子吗? (3认同)

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有时感觉有点怪异和不明确的,如果你正在使用的功能观点看法).

  • 虽然XAML本质上是非常声明的,但MVVM是否真的鼓励编程的功能?视图模型的整个概念,其工作是跟踪视图的状态(并实现一个名为`INotifyPropertyChanged`的所有事物的接口),这似乎与FP对话.我绝对不是FP的专家,也许我过分关注不变性方面而不是声明性方面,但我很难看到MVVM模式(如通常使用的)是FP的一个例子. (11认同)
  • Steven Pemberton在F#和WPF上写了两篇很棒的帖子,他们在[第二篇文章]末尾用F#_开发了WPF开发的这些帖子(http://stevenpemberton.net/blog/2015/05/11/FSharp-WPF-第2部分/)增加了这个讨论.另外两个也引起我兴趣的例子是在[事件驱动的MVVM]中使用功能控制器(http://marisks.net/2015/05/11/f-sharp-xaml-event-driven-mvvm/)和在Flying Frog Consultancy的[WPF控制演示](http://www.ffconsultancy.com/products/fsharp_for_visualization/demo5.html)中使用有区别的联合和递归来构建一个简单的界面. (3认同)

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#技术非常容易.

  • +1这反映了我们的经验,使用组合器库和`IObservable`在F#中编写了几个生产GUI. (7认同)

sbl*_*lom 17

无论您使用的是混合功能/ OO语言(如F#或OCaml),还是使用纯函数语言(如Haskell),副作用都降级为IO monad,大多数情况下管理GUI需要大量工作更像是一种"副作用",而不像纯粹的功能算法.

也就是说,功能GUI已经有了一些非常可靠的研究.甚至还有一些(大部分)功能性工具包,如FudgetsFranTk.

  • "功能GUI"链接断开:(缓存:http://webcache.googleusercontent.com/search?q = cache:http://www.skskell.org/jcp/hw04.pdf (6认同)

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(遗憾的是此刻已被打破)


jhe*_*dus 6

Elliot关于FRP的演讲可以在这里找到.

此外,不是一个真正的答案,而是一个评论和一些想法:不知何故,术语"功能GUI"似乎有点像矛盾(纯粹和IO在同一术语).

但我的模糊理解是,功能性GUI编程是关于声明性地定义时间相关函数,该函数采用(实际)时间相关的用户输入并产生时间相关的GUI输出.

换句话说,这个函数被声明地定义为微分方程,而不是强制使用可变状态的算法.

因此,在传统的FP中,使用时间无关的功能,而在FRP中,使用时间相关的功能作为用于描述程序的构建块.

让我们考虑模拟用户可以与之交互的弹簧上的球.球的位置是图形输出(在屏幕上),用户推球是按键(输入).

在FRP中描述这个模拟程序(根据我的理解)是通过单个微分方程(声明性地)来完成的:加速度*质量=弹簧拉伸*弹簧常数+用户施加的力.

这是一段关于ELM的视频,展示了这一观点.


sao*_*lof 6

自从第一次提出这个问题以来,功能性反应式编程已经成为Elm的主流.

我建议在http://elm-lang.org上查看它,它还有一些真正优秀的交互式教程,介绍如何制作功能齐全的浏览器内GUI.

它允许您创建功能完备的GUI,您需要自己提供的代码只包含纯函数.我个人发现它比各种Haskell GUI框架更容易进入.


Eri*_*lun 5

截至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组件.