哪个更适合使用 Haskell、wxWidgets(通过wxHaskell)或 GTK(通过Gtk2HS)开发 GUI 应用程序?
各自的优缺点是什么?它是否因您所针对的平台而异(我主要在 OS X 上工作,但也希望我的程序也可以在 Linux 和 Windows 上工作)?
[免责声明:我是 wxHaskell 维护者]
两者都是稳定且相当完整的 GUI 绑定,您可以放心地为大多数项目选择其中任何一个。两者都有某种程度的“高级”Haskell 绑定,但在这两种情况下,您都需要使用相当命令式的“C”风格编码来完成工作。我的印象是 wxHaskell 允许您在更高级别的绑定上花费更多时间,但我没有做太多 GTK2HS,无论如何,您肯定会发现自己正在为这两个库的包装器工作 -而且我认为这两种情况下的整体编程“复杂性”是相似的。
因此,让我们以基本功能为前提,专注于差异。请注意,我真的相信 GTK2HS 是一部出色的作品,如果您选择它,您会很高兴。我在下面所说的大部分内容都是个人对差异的看法,以及我选择自己使用 wxHaskell 的原因。
GTK2HS 有一个更大的团队在做这件事,并且更经常地发布。wxHaskell 更新不那么频繁,但核心团队很活跃,并且有定期的错误修复,但主要新功能的添加速度比我们想要的要慢(我们都有日常工作)。
wxHaskell 在所有支持的平台上开箱即用地提供真正的原生应用程序外观。当然,GTK2HS 在 Linux 上是原生的,并且在 Windows 上具有相当不错的原生主题(即足以满足除了学究之外的所有人......),但在 OSX 上具有 GTK 外观和感觉,并且取决于安装了 X11。我相信一个 OSX 'native' GTK 库正在开发中,但被认为相对不成熟。一旦这稳定下来,GTK2HS 应该能够轻松地受益于相同的“部分原生”外观和感觉(例如GTK OSX screenshot)。
如果您不在 Linux 上,wxHaskell 可能更容易构建(如果您使用 Linux 托管,GTK2HS 可能更容易),但说实话,两者的构建都非常复杂,因为在这两种情况下都存在大量依赖项。
分发基于 wxHaskell 的应用程序稍微容易一些(恕我直言),因为它具有较少的库依赖关系。我在 Windows 上主要使用 InnoSetup 分发应用程序,在 OSX 上作为 App 包分发。我承认只需要少量的额外工作,GTK2HS 也可以做到这一点,所以这可能是支持 wxHaskell 的最弱论据。
我个人认为 wxHaskell 对闭源(例如商业)开发更友好。当然,这是无休止的火焰战争的主题,所以我只会说 wxHaskell 是在wxWidgets 许可下的,它明确地允许闭源开发。GTK2HS 是 LGPL,因此您需要询问您的律师——尽管我必须明确指出,许多人和公司已经得出结论,LGPL 与商业开发兼容;我工作的公司的律师认为这不适合我们的项目。
我认为如果 Linux 是我的主要开发和交付平台,我可能会使用 GTK2HS。然而事实并非如此:我主要向 Windows 提供偶尔的 OSX,我认为 wxHaskell 更适合这些平台,尽管这两个选项都支持所有三个平台。
我希望这对您的选择有所帮助。
一个考虑因素是,目前让 wxHaskell 在 Mac OS X 上本地工作稍微容易一些。GTK2HS 依赖于 GTK,它确实有一个在 Mac OS X 上使用本地小部件的实现,但该实现不像 wxWidgets 实现那样容易构建对于 Mac OS X 是。
因此,如果你想开发在没有 X11.app 的情况下运行的代码,目前你最好使用 wxHaskell。
但是请注意,这正在迅速改变: http ://www.haskell.org/haskellwiki/Gtk2Hs#Using_the_GTK.2B_OS_X_Framework 展示了如何在 Mac OS X 上使用 GTK2HS 和原生 GTK+。
GTK2HS 的一大优势是其对 GLADE 的支持,使简单 UI 的开发非常快速。wxHaskell 中更高级别的组合器减轻了大部分优势,但它们确实需要更深入地了解您希望界面的外观和行为方式,因此更难以探索性方式使用。
我有相当不完整的信息,但是由于您还没有答案,也许不完整的信息总比没有好。
要问的问题是:该工具包只是对类 C 功能的包装,还是有一个额外的层为工具包提供了一个更“原生 Haskell-like”API?当 wxHaskell 在 Haskell 研讨会上首次发布时,原生 Haskell API 的开发看起来非常有希望,但仍然不完整。看起来 wxHaskell 的“Haskellized”API 似乎仍在开发中,而 Gtk2Hs 项目根本没有提到这个问题。出于这个原因,我推荐 wxHaskell。
就个人而言,我会研究某种反应式包/扩展。它似乎与范式更接近。您可以以声明方式执行它,而不是命令式地指定图形内容。示例(不代表任何特定语言或实现):
x, y, z :: Int
click, buttonclicked :: Bool
x = <X coordinate of mouse>
y = <Y coordinate of mouse>
click = <Whether mouse button is currently being pressed>
z = x + y
buttonclicked = (x == 10 && y == 10 && click)
每次 x 和 y 更改时,Buttonclicked 和 z 都会自动更新。
然后你可以在某个地方有一些看起来像这样的逻辑:
if buttonclicked then <do something> else <do something else>
不过,这一切都非常模糊。看看一些真正的反应式接口