I'm quite new to Haskell and Snap framework. I'm trying to implement a REST API server but I have some problems querying the Postgresql database using snaplet-postgresql-simple
.
queryDatabase::(B.ByteString,B.ByteString) ->[Interactions]
queryDatabase (drug1,drug2) = do
interaction <- query "SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?" ((B.unpack drug1)::String, (B.unpack drug2)::String):: [Interactions]
return interaction
getDrugList :: Handler b InteractionsService ()
getDrugList = do
drugList <- getQueryParam "list"
let drugs = getDrugPairs $ show drugList
let interactionPairs = map queryDatabase drugs
modifyResponse $ setHeader "Content-type" "application/json"
writeLBS . encode $ (interactionPairs :: [[Interactions]])
The idea is that when the following request is made curl -XGET localhost:8000/api/interactions/drugs?list=drug1,drug2,drug3
the getDrugList
function is called. In drugs
I save the pairs of drugs as a list of tuples [(drug1,drug2),(drug1,drug3),(drug2,drug3)]
and after that I map the function queryDatabase
on the list. The problem is that when I try to compile, I get the following error:
• Couldn't match type '[r0]' with 'Interactions'
Expected type: [Interactions]
Actual type: [[r0]]
• In a stmt of a 'do' block:
interaction <- query
"SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?"
((B.unpack drug1) :: String, (B.unpack drug2) :: String) ::
[Interactions]
In the expression:
do interaction <- query
"SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?"
((B.unpack drug1) :: String, (B.unpack drug2) :: String) ::
[Interactions]
return interaction
In an equation for 'queryDatabase':
queryDatabase (drug1, drug2)
= do interaction <- query
"SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?"
((B.unpack drug1) :: String, (B.unpack drug2) :: String) ::
[Interactions]
return interaction
|
37 | interaction <- query "SELECT drug1name,drug2name,interactioncode FROM interactions WHERE drug1name = ? and drug2name = ?" ((B.unpack drug1)::String, (B.unpack drug2)::String):: [Interactions]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The Interactions data type is defined as:
data Interactions = Interactions
{
drug1name :: T.Text
, drug2name :: T.Text
, druginteraction :: Int
}
instance FromRow Interactions where
fromRow = Interactions <$> field
<*> field
<*> field
instance ToJSON Interactions where
toJSON (Interactions drug1name drug2name interaction) = object [ "drug1name" .= drug1name
, "drug2name" .= drug2name
, "interaction" .= interaction]
Any help is appreciated. I don't have any ideas on how to make it compile and work.
UPDATE
I found a workaround, probably not the best one.
makeQuery::B.ByteString->B.ByteString->Query
makeQuery drug1 drug2 = DS.fromString ("SELECT drug1,drug2,interaction FROM interactions WHERE drug1 = '"++(B.unpack drug1)++"' and drug2 = '"++(B.unpack drug2)++"'")
getDrugList :: Handler b InteractionsService ()
getDrugList = do
drugList <- getQueryParam "list"
let drugs = getDrugPairs $ show drugList
modifyResponse $ setHeader "Content-type" "application/json"
forM_ drugs $ \(drug1,drug2) -> do
let theQuery = makeQuery drug1 drug2
pair<-query_ theQuery
writeLBS . encode $ (pair::[Interactions])