我是haskell的新手,真的很难过。但这扩展了我的想法,所以我们开始吧。我正在尝试运行一个非常简单的 Web 服务器来查询 Postgres DB 并应将结果作为 JSON 返回。
查询非常简单:“Select id,data from MYTABLE where id = 1”
但是 haskell 的类型系统现在正在杀死我,我的行为的最终类型不匹配。我正在使用Spock和PostgreSQL-Simple作为组合。
大多数教程对于我想做的事情要么简单,要么困难。我介于两者之间,错过了很多对 Haskell 的理解,我以前的很多问题我已经通过简单的复制和粘贴解决了,并且得到了一个简单的版本。
但是,一旦我尝试传递路由变量,我就失败了。这是我的工作版本。我的数据库表在这里称为“信封”,重要的调用是它说的get "json"
:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleInstances #-}
module Main where
import Web.Spock
import Web.Spock.Config
import Database.PostgreSQL.Simple
import Data.Pool
import Data.Aeson (ToJSON(toJSON), object, (.=),Value)
import Database.PostgreSQL.Simple.FromRow
type AppAction a = SpockActionCtx () Connection AppSession AppState a
data AppState = EmptyState
data AppSession = EmptySession
data Envelope = Envelope { envId :: Int, envData :: Value } deriving Show
instance FromRow Envelope where
fromRow = Envelope <$> field <*> field
instance ToJSON Envelope where
toJSON (Envelope envA envB) = object [ "id" .= envA, "data" .= envB ]
main :: IO ()
main =
do pool<-createPool (connect (ConnectInfo "localhost" 5432 "" "" "envelopes") ) close 1 10 10
spockCfg <- defaultSpockCfg EmptySession (PCPool pool) EmptyState
runSpock 8080 (spock spockCfg app)
app :: SpockM Connection AppSession AppState ()
app = do
get root $
text "Hello World!"
get "json" $ do
xs<-runQuery $ \conn ->
query_ conn "select id,data from envelope where id = 1"
json (xs::[Envelope])
然后我尝试使用 lambda 函数传递信封 ID,为此我还需要将 PostgreSQL-Simple 更改query_
为query
:
get ( "json" <//> var ) $ \eid -> do
xs<-runQuery $ \conn ->
query conn "select id,data from envelope where id = ?" (eid :: Int)
json (xs::[Envelope])
我得到的错误说:
No instance for (ToRow Int) arising from a use of ‘query’
In the expression:
query conn "select id,data from envelope where id = ?" (eid :: Int)
In the second argument of ‘($)’, namely
‘\ conn
-> query
conn "select id,data from envelope where id = ?" (eid :: Int)’
In a stmt of a 'do' block:
xs <- runQuery
$ \ conn
-> query
conn "select id,data from envelope where id = ?" (eid :: Int)
即使没有 lambda 函数,我也无法仅返回查询中的第一项。
完整的源代码可以在bitbucket上找到
我希望有人有时间在这里帮助我。感谢您的阅读。