如何在整个web应用程序堆栈中利用Haskell类型的安全性
How can you leverage Haskell type safety through the whole web application stack?
我想知道以CRUD为中心的web应用程序能从Haskell的类型系统中受益多少,尤其是当前端使用像AngularJS这样的Javascript MVC框架构建时,该框架传递无类型的数据对象。
在我看来,一旦您将Haskell数据类型转换为JSON对象,并将其传递给一个沉重的JavaScriptMVC框架层,那么将Haskell's类型系统作为web堆栈的一部分的好处就会开始显著削弱,因为没有办法让类型检查器确保整个web应用程序中数据流的类型完整性。
例如,您可以更改数据库模式和相关的Haskell类型,但类型检查器无法告诉您JavaScriptMVC前端的哪些部分也需要更新。我认为这是个问题。
我是否正确地陈述了这个问题?如果是,Haskell web应用程序开发人员在这一点上可以给出什么建议?
自从我们最近开始了一个使用大量javascript前端的项目以来,我们一直在努力解决这个完全相同的问题。我的轶事观察是,与之前使用Snap并使用Heist生成HTML的应用程序相比,javascript应用程序中的错误要多得多。我们还没有决定任何事情,但以下是我们一直在考虑的一些可能的解决方案:
精简Javascript包装器
- CoffeeScript
- TypeScript
- Dart
这些解决方案对我来说非常不满意。在Javascript上有了一些改进,但并没有给我带来Haskell带来的东西。
更具功能性和类型安全性的前端语言
- Fay是Haskell的一个子集,可以编译成Javascript。它确实有一些吸引力,但并不能让你访问所有的Haskell。上次我听说它不支持类型类,我想这很快就会成为一个障碍
- Elm
- 罗伊
这些解决方案(以及前一组)的问题是,如果您的后端是用Haskell编写的,那么您仍然存在阻抗不匹配,因为您的前端语言不是Haskell。这使得您的代码不那么枯燥,因为您最终必须在Haskell和前端语言中定义相同的数据结构。当您在Haskell中更改它们时,不会出现指示前端代码需要更改的位置的错误。应用程序刚坏。
将Haskell编译为Javascript
城里的新游戏是ghcjs。这是一个非常有前景的项目,但我认为它至少在GHC7.8发布之前是不可行的。这有望在下周内实现。一旦7.8问世,你仍然需要考虑到ghcjs仍然是非常新的。即使在假设它100%完成了功能并且第一个版本运行良好的情况下,你仍然必须记住,在Haskell+ghcjs像Angular、Ember等高级javascript框架一样有效之前,还必须构建相当多的基础设施。
2016年9月更新:现在,在我最初写下这个答案近三年后,GHCJS有了很大的改进。还有更多改进的空间,但我已经将其用于生产应用程序,效果非常好。当与Reflex FRP库相结合时,它的功能尤其强大,这使得构建反应UI变得更加容易。
使用EDSL从Haskell生成Javascript
如果您有一个相对受限的问题,那么可能在生成javascript的EDSL上完成所有应用程序工作。我们已经有了出色的jmacro包来处理生成Javascript的低级别问题。您可以利用这一点,生成使用适合您的应用程序的任何其他javascript库的代码。这可以是javascript+jquery、D3.js,甚至可以是使用Angular或Ember等更高级别javascript框架的代码。我倾向于认为Angular比Ember更容易生成代码,因为它简单且封装性更强。
Greenfield是为浏览器中的函数语言设计的字节码虚拟机
这只是我的一个不切实际的想法。我认为这并不实际,因为这需要大量的工作,而且很难被采用。但我至少想提一下完整性的想法。其他人指出,asm.js几乎已经是这样了。可能是这样,但从一开始就将尾调用优化之类的东西设计到VM级别会很好。
在我看来,简单的解决方案-从haskell数据声明(或其他api方案描述)生成typescript接口,并将typescript用于前端部分。它为那些不了解haskell但了解Javascript的人提供了从事项目的机会。
例如
data RpcResponse = RpcResponse { number :: Int, string :: Maybe String }
编译为
interface RpcResponse {
number : number,
string?: string
}
函数parseRpcResponseJson具有Typescript类型
parseRpcResponseJson(response: string): Option<RpcResponse>;
- 为什么会出现错误;未捕获的类型错误:undefined不是函数;
- 如何在DOM元素上按类型构建此函数
- 同样,同样的错误'ahorcado.js:26未捕获类型错误:无法读取属性'beginPath'
- YUI3 IO实用程序是否可以根据给定的内容类型标头值自动序列化数据
- Webpack/Rect:遵循egghead.io教程,但出现错误:您可能需要一个合适的加载程序来处理此文件类型
- 如何从querySelectorAll中获取按钮类型
- 如何在输入字段中的按钮的帮助下打开日历,该字段的类型为“=”;日期”;
- 如何将具有文本类型值的var放入jQuery函数中
- javascript解释器如何理解变量的数据类型
- 可变大小的JavaScript字符串如何成为基元类型
- AngularJS指令只识别双向绑定类型
- 在<输入类型=“;文件“/>
- 从查询字符串参数推断出正确的数据类型
- 未捕获的类型错误:无法读取属性'删除'的未定义
- 为什么不'我们在javascript中使用函数参数的数据类型
- Javascript 可选类型提示
- 可以<脚本类型=“;text/javascript”>window.location=“/"</
- 未捕获的类型错误:无法读取属性'name'即使它存在,也无法定义
- 如何在整个web应用程序堆栈中利用Haskell类型的安全性
- Javascript中是否有类似Haskell的类型签名的约定