如何用标准化的,通用的纯函数编程语言Haskell来构建Web?Haskell构建的Web拥有着什么样的优点呢?让我们来看看构建的过程吧 。
文章插图
作者%20|%20William%20Yao
译者%20|弯月,责编%20|%20maozz
出品%20|%20CSDN(ID:CSDNnews)
以下为译文:
Haskell有大量的库可用于满足基本的后台需求,从日志输出到数据库访问,再到Web服务器的定义和路由,应有尽有 。
拥有选择的自由固然很好,但如果你刚刚接触这个领域,那么大量的选择可能会让你目不暇接 。也许你没法自信地判断出这些选择之间的区别 。例如,你需要查询数据库 。
那么,你需要Squeal提供的列名强保证,以及深度SQL嵌入功能吗?还是青睐Opaleye在保证类型安全的前提下的简单性?或者只是使用简单的postgresql-simple就好?还是使用Selda?或者……
我用最简单的库写了一个Web应用程序,一方面是想告诉你,你不需要担心技术栈是否足够先进,另一方面也是我自己的学习过程 。
如果你不知道怎样用Haskell构建真正的应用程序,为什么不去学习呢?我会尽可能保持代码的简单性 。
点击此处可查看源代码(https://gitlab.com/williamyaoh/haskell-web-stack) 。
下面我们来看一看我选择的这些库,以及它们的功能,还有这个应用程序的功能 。
1.这个Web应用程序究竟是什么呢?
它是一个网站,用户可以在这个网站上创建定时器和做笔记 。
我举个例子说明该网站的用途:某人想设置多个定时器来跟踪多个反应物的过程,同时用笔记来记录他们需要关心的事情、下次制作配方时需要改进的事情,等等 。
再举一个例子,某个人在玩MOBA游戏,比如英雄联盟或者刀塔2,他们可以在另一台显示器上打开一个页面来跟踪关键技能的冷却时间,同时用笔记记录宏操作、对手的组合,以及团战时需要关注技的冷却等 。
在这个应用程序中我将演示:
- 会话,用户可以刷新页面,或者关闭页面后再打开,但在打开之后应该看到相同的内容 。
- 持久化和数据库访问,我们需要将每个用户的定时器和笔记保存下来 。另一个需求是定时器需要维持剩余的时间(用户设置了一个30分钟的定时器,然后不小心关闭了页面,应该如何?)
- 运行时的配置,因为我们不能把数据库连接的信息硬编码到代码里 。
- 日志 。日志对于Web应用的作用不言而喻 。
路由和Web服务器:Spock
最终我选择了Spock,因为它易于使用 。如果你用过Ruby的Sinatra,那么Spock应该不会陌生 。Spock也自带了会话管理,这一点非常好 。
例如,定义一个拥有几条路由的服务器,返回html和JSON,代码大致如下:
{-# LANGUAGE OverloadedStrings #-}
import Web.Spock as Spock
import Web.Spock.Config as Spock
import Data.Aeson as A
main :: IO
main = do
spockCfg <- defaultSpockCfg PCNoDatabase
runSpock 3000 $ spock spockCfg $ do
get root $ do
Spock.html "<div>Hello world!</div>"
get "users" $ do
Spock.json (A.object [ "users" .= users ])
get ("users" <//> var <//> "friends") $ \userID -> do
Spock.json (A.object [ "userID" .= (userID :: Int), "friends" .= A. ])
where users :: [String]
users = ["bob", "alice"]
数据库访问:postgresql-simple
postgresql-simple基本上只允许您对数据库运行原始SQL查询,而没有多余的装饰,例如防止注入攻击 。它可以实现您的期望,仅此而已 。
{-# LANGUAGE OverloadedStrings #-}
import Database.PostgreSQL.Simple
userLoginsQuery :: Query
userLoginsQuery =
"SELECT l.user_id, COUNT(1) FROM logins l GROUP BY l.user_id;"
getUserLogins :: Connection -> IO [(Int, Int)]
getUserLogins conn = query_ conn userLoginsQuery
数据库访问:postgresql-simple
postgresql-simple可以让你在数据库上运行原始的SQL查询,它只提供最基本的额外处理,比如防止注入攻击等 。它仅完成你需要的东西,没有任何额外的功能 。
{-# LANGUAGE OverloadedStrings #-}
import Database.PostgreSQL.Simple
userLoginsQuery :: Query
userLoginsQuery =
"SELECT l.user_id, COUNT(1) FROM logins l GROUP BY l.user_id;"
getUserLogins :: Connection -> IO [(Int, Int)]
推荐阅读
- 常用网线的分类及传输距离,终于知道为什么网速这么差了
- Linux 下你所不知道的 7 个 SSH 命令用法
- Ubuntu 防火墙安装、启用、查看状态等常用命令
- 治怔忡藥酒的功效与作用
- 治中滿鼓脹酒方的功效与作用
- 肘后疗劳疟鳖甲酒方的功效与作用
- 种玉酒的功效与作用
- 茱萸酒的功效与作用
- 猪胆酒的功效与作用
- 治腰脚诸病酒方的功效与作用