function性GUI编程是否可行?

我最近抓住了FP错误(试图学习Haskell),而且我对迄今为止所看到的(一stream的函数,懒惰的评估以及所有其他的好东西)印象深刻。 我还没有专家,但是我已经开始发现,在function上比在基本algorithm中推理更容易(而且我在遇到麻烦的时候还要回去)。

但是,目前的FP似乎平坦的一个领域是GUI编程。 Haskell方法似乎只是包装命令式GUI工具包(如GTK +或wxWidgets),并使用“do”块来模拟命令式的风格。 我没有使用F#,但我的理解是,它使用OOP与.NET类做类似的事情。 显然,这样做有一个很好的理由 – 目前的GUI编程都是关于IO和副作用的,所以纯粹的函数式编程在大多数当前的框架中是不可能的。

我的问题是,是否有可能对GUI编程有function的方法? 我很难想象这在实践中会是什么样子。 有没有人知道任何框架,试验或其他,尝试这样的事情(甚至任何框架是从底层devise的function语言)? 或者是只使用混合方法的解决scheme,OOP用于GUI部件和FP用于逻辑? (我只是出于好奇而问 – 我很喜欢认为FP是“未来”,但GUI编程似乎是一个相当大的空缺)。

Haskell方法似乎只是包装命令式GUI工具包(如GTK +或wxWidgets),并使用“do”块来模拟命令式

这不是真正的“Haskell方法”,而是通过一个命令性的界面,直接绑定到命令式GUI工具包。 Haskell碰巧有相当突出的绑定。

有几个适度的成熟或更实验性的纯function性/声明性的GUI方法,主要是在Haskell中,主要使用function性反应式编程。

一个例子是

对于那些不熟悉Haskell的人来说,Flapjax, http ://www.flapjax-lang.org/是一个在JavaScript之上的function反应式编程的实现。

我的问题是,是否有可能对GUI编程有function的方法?

您正在寻找的关键词是“function性反应式编程”(FRP)。

Conal Elliott和其他一些人为了find合适的FRP抽象而做了一点小小的工作。 Haskell中有几个FRP概念的实现。

你可以考虑从Conal最近推出的“Push-Pull Functional Reactive Programming”文章开始,但是还有其他一些(旧的)实现,其中一些是从haskell.org网站链接的。 康纳尔具有涵盖整个领域的诀窍,他的论文可以阅读而不参考之前的内容。

为了了解这种方法如何用于GUI开发,您可能需要看看Fudgets ,尽pipe这些方法在90年代中期被devise出来 ,但在现在已经变得有点长久了,它提供了一个坚实的FRP方法到GUIdevise。

Windows Presentation Foundation是一个certificatefunction性方法在GUI编程中非常有效的certificate。 它具有许多function方面,WPF代码(searchMVVM模式)的“好”WPF代码强调function性方法而非强制性方法。 我可以勇敢地声称,WPF是最成功的现实世界的functionGUI工具包:-)

WPF描述了XAML中的用户界面(尽pipe你可以重写它来查看C#或F#),所以要创build一些用户界面,你可以这样写:

<!-- 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> 

此外,WPF还允许您使用另一组声明标签声明性地描述animation和对事件的反应(同样的事情可以写成C#/ F#代码):

 <DoubleAnimation Storyboard.TargetName="greenEllipse" Storyboard.TargetProperty="(Canvas.Left)" From="0.0" To="100.0" Duration="0:0:5" /> 

实际上,我认为WPF与Haskell的FRP有许多共同之处(尽pipe我相信WPFdevise者不了解FRP,这有点不幸 – 如果你使用的function有时会让WPF感到有点奇怪和不清楚观点看法)。

我实际上会说function性编程(F#)比用C#更好的用户界面编程工具。 你只需要稍微思考一下这个问题。

我在第16章的函数式编程书中讨论了这个主题,但是有一个免费的摘录 ,它显示了(IMHO)你可以在F#中使用的最有趣的模式。 假设您要实现矩形的绘制(用户按下button,移动鼠标并释放button)。 在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#风格),但是它避免了使用可变状态来存储绘图的当前状态和存储初始位置。 尽pipe如此,我还是写了一个图书馆,把它作为我的硕士论文的一部分,在接下来的几天我的博客上可以find它。

function性react native编程是一种更为实用的方法,但是我觉得使用起来有些困难,因为它依赖于相当先进的Haskellfunction(如箭头)。 但是,在很多情况下,它是非常优雅的。 它的局限性是你不能轻易地编码一个状态机(这是一个有用的心理模型反应式程序)。 这很容易使用上面的F#技术。

无论您是使用F#还是OCaml这样的混合function/ OO语言,或者像Haskell这样的纯粹function性语言,其副作用都归于IO monad, 大多数情况下,需要大量的工作来pipe理GUI更像一个“副作用”,而不是像一个纯粹的functionalgorithm。

也就是说,对function性graphics用户界面进行了一些非常扎实的研究。 甚至有一些(大部分)function工具包,如Fudgets或FranTk 。

您可以通过F#上的Don Syme来查看这个系列,他演示了创build一个gui。 以下链接是系列的第三部分(您可以从那里链接到其他两个部分)。

使用F#进行WPF开发将是一个非常有趣的GUI范例…

http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-3-of-3/

function反应规划背后的一个令人大开眼界的想法是有一个事件处理函数产生对事件和下一个事件处理函数的双重反应。 因此,一个演进系统被表示为一系列事件处理函数。

对我来说,学习瑜伽成为了正确地获得function生产function的关键。 关于Yampa有一些很好的文章。 我推荐Yampa商场:

~nhn/Talks/HW2003-YampaArcade.pdf (幻灯片,PDF) http://www.cs.nott.ac.uk/~nhn/Publications/hw2003。; pdf (全文,PDF)

在Haskell.org有一个关于Yampa的wiki页面

http://www.haskell.org/haskellwiki/Yampa

原番薯主页:

http://www.haskell.org/yampa (不幸现在被打破了)

埃利奥特关于玻璃钢的谈话可以在这里find。

另外,不是一个真正的答案,而是一个评论和一些想法 :不知何故,“function性GUI”这个词似乎有点像一个矛盾(纯粹和IO在同一个词)。

但是我的模糊的理解是,function性的GUI编程是关于声明性地定义一个时间相关的函数,它取决于(实时的)时间相关的用户input并产生时间相关的GUI输出。

换句话说,这个函数被定义为一个微分方程,而不是一个强制使用可变状态的algorithm。

所以在传统的FP中使用时间无关的函数,而在FRP中使用时间相关的函数作为构build块来描述程序。

让我们考虑在用户可以与之互动的弹簧上模拟一个球。 球的位置是graphics输出(在屏幕上),用户推球是按键(input)。

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

这是一个关于ELM的video,它说明了这个观点。

截至2016年,Haskell还有几个比较成熟的FRP框架,如钠和reflection(还有Netwire)。

关于函数式响应式编程的Manning书籍展示了钠的Java版本,并举例说明了FRP GUI代码库与命令式和基于Actor的方法相比的行为和缩放比例。

最近还有一篇关于Arrowed玻璃钢的文章,以及在遵循法律的纯FRP环境中引入副作用,IO和突变的前景: http : //haskell.cs.yale.edu/wp-content/uploads/2015/10/ dwc-yale-formatted-dissertation.pdf 。

另外值得注意的是,ReactJS和Angular等JavaScript框架已经或者正在朝着使用FRP或其他function方法实现可缩放和可组合的GUI组件。

自从首先提出这个问题以来,function反应式编程已经被Elm变得更加主stream了。

我build议在http://elm-lang.org上查看,它也有一些真正优秀的交互式教程,介绍如何在浏览器中创build一个function齐全的GUI。;

它允许您创buildfunction完备的GUI,您需要提供的代码只包含纯函数。 我个人发现比各种Haskell GUI框架更容易得到。

像XUL这样的标记语言允许您以声明的方式构build一个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 /

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

我只是在F#的背景下讲话。

-Fahad

所有这些其他的答案都是在函数式编程的基础上build立起来的,但是做出了很多自己的devise决定。 一个基本上完全由函数和简单的抽象数据types构成的库是gloss 。 这是来自源的playfunction的types

 -- | Play a game in a window. Like `simulate`, but you manage your own input events. play :: Display -- ^ Display mode. -> Color -- ^ Background color. -> Int -- ^ Number of simulation steps to take for each second of real time. -> world -- ^ The initial world. -> (world -> Picture) -- ^ A function to convert the world a picture. -> (Event -> world -> world) -- ^ A function to handle input events. -> (Float -> world -> world) -- ^ A function to step the world one iteration. -- It is passed the period of time (in seconds) needing to be advanced. -> IO () 

正如你所看到的,它完全可以通过提供简单抽象types的纯函数来工作,其他库可以帮助你。

函数式编程可能从我上大学的时候就开始了,但是我记得函数式编程系统的主要观点是阻止程序员创build任何“副作用”。 然而,由于创build的副作用,用户购买软件,例如更新UI。