亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

如何用標(biāo)準(zhǔn)化的,通用的純函數(shù)編程語(yǔ)言Haskell來構(gòu)建Web?Haskell構(gòu)建的Web擁有著什么樣的優(yōu)點(diǎn)呢?讓我們來看看構(gòu)建的過程吧。

快速用 Haskell 構(gòu)建超級(jí)簡(jiǎn)單的 Web 技術(shù)棧

作者%20|%20William%20Yao

譯者%20|彎月,責(zé)編%20|%20maozz

出品%20|%20CSDN(ID:CSDNnews)

以下為譯文:

Haskell有大量的庫(kù)可用于滿足基本的后臺(tái)需求,從日志輸出到數(shù)據(jù)庫(kù)訪問,再到Web服務(wù)器的定義和路由,應(yīng)有盡有。

擁有選擇的自由固然很好,但如果你剛剛接觸這個(gè)領(lǐng)域,那么大量的選擇可能會(huì)讓你目不暇接。也許你沒法自信地判斷出這些選擇之間的區(qū)別。例如,你需要查詢數(shù)據(jù)庫(kù)。

那么,你需要Squeal提供的列名強(qiáng)保證,以及深度SQL嵌入功能嗎?還是青睞Opaleye在保證類型安全的前提下的簡(jiǎn)單性?或者只是使用簡(jiǎn)單的postgresql-simple就好?還是使用Selda?或者……

我用最簡(jiǎn)單的庫(kù)寫了一個(gè)Web應(yīng)用程序,一方面是想告訴你,你不需要擔(dān)心技術(shù)棧是否足夠先進(jìn),另一方面也是我自己的學(xué)習(xí)過程。

如果你不知道怎樣用Haskell構(gòu)建真正的應(yīng)用程序,為什么不去學(xué)習(xí)呢?我會(huì)盡可能保持代碼的簡(jiǎn)單性。

點(diǎn)擊此處可查看源代碼(https://gitlab.com/williamyaoh/haskell-web-stack)。

下面我們來看一看我選擇的這些庫(kù),以及它們的功能,還有這個(gè)應(yīng)用程序的功能。

1.這個(gè)Web應(yīng)用程序究竟是什么呢?

它是一個(gè)網(wǎng)站,用戶可以在這個(gè)網(wǎng)站上創(chuàng)建定時(shí)器和做筆記。

我舉個(gè)例子說明該網(wǎng)站的用途:某人想設(shè)置多個(gè)定時(shí)器來跟蹤多個(gè)反應(yīng)物的過程,同時(shí)用筆記來記錄他們需要關(guān)心的事情、下次制作配方時(shí)需要改進(jìn)的事情,等等。

再舉一個(gè)例子,某個(gè)人在玩MOBA游戲,比如英雄聯(lián)盟或者刀塔2,他們可以在另一臺(tái)顯示器上打開一個(gè)頁(yè)面來跟蹤關(guān)鍵技能的冷卻時(shí)間,同時(shí)用筆記記錄宏操作、對(duì)手的組合,以及團(tuán)戰(zhàn)時(shí)需要關(guān)注技的冷卻等。

在這個(gè)應(yīng)用程序中我將演示:

  • 會(huì)話,用戶可以刷新頁(yè)面,或者關(guān)閉頁(yè)面后再打開,但在打開之后應(yīng)該看到相同的內(nèi)容。

  • 持久化和數(shù)據(jù)庫(kù)訪問,我們需要將每個(gè)用戶的定時(shí)器和筆記保存下來。另一個(gè)需求是定時(shí)器需要維持剩余的時(shí)間(用戶設(shè)置了一個(gè)30分鐘的定時(shí)器,然后不小心關(guān)閉了頁(yè)面,應(yīng)該如何?)

  • 運(yùn)行時(shí)的配置,因?yàn)槲覀儾荒馨褦?shù)據(jù)庫(kù)連接的信息硬編碼到代碼里。

  • 日志。日志對(duì)于Web應(yīng)用的作用不言而喻。

2.我用到了哪些庫(kù)?

路由和Web服務(wù)器:Spock

最終我選擇了Spock,因?yàn)樗子谑褂谩H绻阌眠^Ruby的Sinatra,那么Spock應(yīng)該不會(huì)陌生。Spock也自帶了會(huì)話管理,這一點(diǎn)非常好。

例如,定義一個(gè)擁有幾條路由的服務(wù)器,返回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"]

數(shù)據(jù)庫(kù)訪問:postgresql-simple

postgresql-simple基本上只允許您對(duì)數(shù)據(jù)庫(kù)運(yùn)行原始SQL查詢,而沒有多余的裝飾,例如防止注入攻擊。它可以實(shí)現(xiàn)您的期望,僅此而已。

{-# 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

數(shù)據(jù)庫(kù)訪問:postgresql-simple

postgresql-simple可以讓你在數(shù)據(jù)庫(kù)上運(yùn)行原始的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

配置:configurator

configurator能夠從文件中讀取配置,并解析成Haskell數(shù)據(jù)類型。與普通的配置文件讀取器相比它的功能要多一些。

如果你習(xí)慣了直接讀取配置文件,那么configurator還有一些額外功能。例如,配置項(xiàng)可以嵌套分組,configurator還提供了熱重載來監(jiān)視配置文件變化。


 

# An example config file.

App_name = "The Whispering Fog"

db {

pool {

stripes = 4

resource_ttl = 300

}

username = "pallas"

password = "thefalloflatinium"

dbname = "italy"

}


 

{-# LANGUAGE OverloadedStrings #-}

import Data.Configurator as Cfg

import Database.PostgreSQL.Simple

data MyAppConfig = MyAppConfig

{ appName :: String

, appDBConnection :: Connection

}

getAppConfig :: IO MyAppConfig

getAppConfig = do

cfgFile <- Cfg.load ["app-configuration.cfg"]

name <- Cfg.require cfgFile "app_name"

conn <- do

username <- Cfg.require cfgFile "db.username"

password <- Cfg.require cfgFile "db.password"

dbname <- Cfg.require cfgFile "db.dbname"

connect $ defaultConnectInfo

{ connectUser = username

, connectPassword = password

, connectDatabase = dbname

}

pure $ MyAppConfig

{ appName = name

, appDBConnection = conn

}

日志:fast-logger

fast-logger提供了一個(gè)相對(duì)簡(jiǎn)單易用的日志解決方案。在Web應(yīng)用程序的示例中,我只輸出到了stderr,但它還可以支持輸出日志到文件。雖然它支持許多類型,但絕大多數(shù)情況下,你需要定義一個(gè)輔助函數(shù),接收一個(gè)LoggerSet,以及需要記錄的信息。


 

import System.Log.FastLogger as Log

logMsg :: Log.LoggerSet -> String -> IO

logMsg logSet msg =

Log.pushLogStrLn logSet (Log.toLogStr msg)

doSomething :: IO

doSomething = do

logSet <- Log.newStderrLoggerSet Log.defaultBufSize

logMsg logSet "message 1"

logMsg logSet "message 2"

HTML生成:blaze-html

盡管本項(xiàng)目的后臺(tái)并不需要生成太多HTML,但值得一提的是,blaze-html正是我需要的。

基本上它就是將HTML淺層嵌入到了Haskell DSL中。如果你會(huì)編寫HTML,那你就會(huì)使用這個(gè)庫(kù)。


 

{-# LANGUAGE OverloadedStrings #-}

import Data.ByteString.Lazy

import Text.Blaze.Html5 as HTML

import Text.Blaze.Html5.Attributes as HTML hiding ( title )

import Text.Blaze.Html.Renderer.Utf8 as HTML

dashboardHTML :: HTML.Html

dashboardHTML = HTML.html $

HTML.docTypeHtml $ do

HTML.head $ do

HTML.title "Timers and Notes"

HTML.meta ! HTML.charset "utf-8"

HTML.script ! HTML.src "/js/bundle.js" $ ""

HTML.body $ do

HTML.div ! HTML.id "content" $ ""

dashboardBytes :: ByteString

dashboardBytes = HTML.renderHtml dashboardHTML

構(gòu)建前端:make + npm

沒錯(cuò),它們并不是庫(kù)。但我們依然需要某種JAVAScript前端,因?yàn)槎〞r(shí)器需要實(shí)時(shí)更新。Webpack能夠生成JS包,而Make能夠組裝最終的應(yīng)用程序。

這些東西無(wú)需我多說,網(wǎng)上有很多相關(guān)的資源。

3.我必須要用這些庫(kù)嗎?

當(dāng)然不是。如果你第一次接觸Haskell,那么有這些疑問是很自然的。不要讓這篇文章限制了你的思路。盡管這個(gè)應(yīng)用程序可以運(yùn)行,但許多部分用于生產(chǎn)環(huán)境下的Haskell時(shí)并不理想。

例如,許多Haskell程序員很可能會(huì)使用Servant而不是Spock來定義API端點(diǎn)。如果你想了解其他庫(kù),那當(dāng)然應(yīng)該跟隨你的直覺。

你可以把這些庫(kù)和這個(gè)應(yīng)用程序作為起點(diǎn)。我建議你用這些代碼作為學(xué)習(xí)的機(jī)會(huì),理解它的原理,然后自己試著修改。Haskell很好的一點(diǎn)就是它非常易于重構(gòu)或者升級(jí),而不會(huì)破壞已有的功能。

一旦掌握了這個(gè)應(yīng)用程序,就可以用更高級(jí)的庫(kù)來替換它們,來獲得更多的保證。同時(shí),這也是一個(gè)增量學(xué)習(xí)的過程。

將數(shù)據(jù)庫(kù)訪問的庫(kù)從postgresql-simple升級(jí)到支持類型安全的庫(kù)。我推薦Opaleye!

將API定義的庫(kù)從Spock升級(jí)到Servant

利用QuickCheck或hedgehog增加自動(dòng)測(cè)試。例如,你可以測(cè)試服務(wù)器的每個(gè)錯(cuò)誤響應(yīng)都返回了JSON格式的錯(cuò)誤信息。

你還可以嘗試替換前端和構(gòu)建系統(tǒng)。

升級(jí)前端,使用PureScript或Elm來替換原始的JavaScript

升級(jí)構(gòu)建系統(tǒng),利用Shake替換make構(gòu)建更健壯的系統(tǒng)

原文:https://williamyaoh.com/posts/2019-11-16-a-dead-simple-web-stack.html

本文為 CSDN 翻譯,轉(zhuǎn)載請(qǐng)注明來源出處。

【End】

分享到:
標(biāo)簽:Haskell
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定