我最近发现了FP错误(试图学习Haskell),到目前为止,我对我所看到的(一流函数、惰性求值和所有其他好东西)印象深刻。我还不是专家,但我已经开始发现对基本算法进行“功能性”推理比命令式推理更容易(而且我很难回到我必须回到的地方)。

The one area where current FP seems to fall flat, however, is GUI programming. The Haskell approach seems to be to just wrap imperative GUI toolkits (such as GTK+ or wxWidgets) and to use "do" blocks to simulate an imperative style. I haven't used F#, but my understanding is that it does something similar using OOP with .NET classes. Obviously, there's a good reason for this--current GUI programming is all about IO and side effects, so purely functional programming isn't possible with most current frameworks.

My question is, is it possible to have a functional approach to GUI programming? I'm having trouble imagining what this would look like in practice. Does anyone know of any frameworks, experimental or otherwise, that try this sort of thing (or even any frameworks that are designed from the ground up for a functional language)? Or is the solution to just use a hybrid approach, with OOP for the GUI parts and FP for the logic? (I'm just asking out of curiosity--I'd love to think that FP is "the future," but GUI programming seems like a pretty large hole to fill.)


当前回答

你可以看看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/

其他回答

像XUL这样的标记语言允许您以声明式的方式构建GUI。

自从第一次提出这个问题以来,函数式响应式编程已经被Elm变得更加主流。

我建议你去http://elm-lang.org上看看,那里也有一些非常优秀的交互式教程,教你如何制作一个功能齐全的浏览器内GUI。

它允许您制作功能齐全的GUI,其中您需要自己提供的代码仅由纯函数组成。我个人认为它比各种Haskell GUI框架更容易上手。

实际上,我想说函数式编程(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 }

这是一种非常必要的方法(在通常实用的f#风格中),但它避免使用可变状态来存储绘图的当前状态和存储初始位置。它可以做得更有功能,我写了一个库,作为我硕士论文的一部分,应该在几天后可以在我的博客上看到。

函数式响应式编程是一种更函数化的方法,但我发现它有点难以使用,因为它依赖于相当高级的Haskell特性(比如箭头)。然而,在大量的情况下,它是非常优雅的。它的局限性在于您不能轻松地对状态机进行编码(这是响应式程序的有用心理模型)。使用上面的f#技术,这是非常容易的。

截至2016年,Haskell还有几个相对成熟的FRP框架,如Sodium和Reflex(还有Netwire)。

Manning关于函数式响应式编程的书展示了Java版本的Sodium,作为工作示例,并举例说明了FRP GUI代码库与命令式和基于Actor的方法相比是如何行为和扩展的。

最近还有一篇关于箭头化FRP的论文,以及将副作用、IO和突变纳入遵守法律的纯FRP环境的前景:http://haskell.cs.yale.edu/wp-content/uploads/2015/10/dwc-yale-formatted-dissertation.pdf。

同样值得注意的是,JavaScript框架(如ReactJS和Angular)以及其他许多框架已经或正在使用FRP或其他函数式方法来实现可伸缩和可组合的GUI组件。

为了解决这个问题,我发布了一些我在使用f#时的想法,

http://fadsworld.wordpress.com/2011/04/13/f-in-the-enterprise-i/ http://fadsworld.wordpress.com/2011/04/17/fin-the-enterprise-ii-2/

我还计划做一个视频教程来完成这个系列,并展示f#如何在UX编程中做出贡献。

这里我只是在f#上下文中讨论。

法赫德