[英]postgres-simple - No instance for (ToRow Int) arising from a use of ‘query’
我是 Haskell 的新手,老實說,我遇到了困難。 但它擴展了我的想法,所以我們走了。 我正在嘗試運行一個非常簡單的 Web 服務器,它查詢 Postgres 數據庫並應將結果作為 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上找到完整的源代碼
我希望有人有時間在這里幫助我。 感謝您的閱讀。
基於soupis help,我還在Postgres-Simple 文檔中找到了相應的部分。 只是為了完成,文檔提到了使用單例列表的替代語法。 因此,您可以簡單地使用方括號而不是使用普通括號,它也可以工作:
query conn "select id,data from envelope where id = ?" [eid :: Int]
此外,特別是在我的示例中,只返回結果中的第一行更有意義,然后結果是直接使用head
函數。 對於需要它的任何其他人,您可以這樣做:
Spock 和 Prelude 都包含head
功能。 為了避免沖突,我決定隱藏 Spocks 函數,因為我無論如何都沒有使用它。
在頂部添加到您的腳本:
import Web.Spock hiding(head)
然后將get
部分更改為:
get ( "json" <//> var ) $ \eid -> do
xs<-runQuery $ \conn ->
query conn "select id,data from envelope where id = ?" [eid :: Int]
json $ head (xs::[Envelope])
完畢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.