Haskell scotty和持久性Rest API

时间:2018-06-27 19:20:28

标签: haskell persistence scotty

我是Haskell的新手。我喜欢用scotty和持久性创建简单的crud rest api。我在一个表todo (title text, description text)中使用sqlite,表中有一些记录。我的观点是以json格式显示enpoint /todos上的所有记录。打印时出现错误

  • Couldn't match expected type ‘Data.Text.Internal.Lazy.Text’
                  with actual type ‘[Entity ToDo]’
    • In the first argument of ‘text’, namely ‘(_ToDo)’
      In a stmt of a 'do' block: text (_ToDo)
      In the second argument of ‘($)’, namely
        ‘do _ToDo <- liftIO readToDo
            text (_ToDo)’
   |
69 |     text(_ToDo)
   |          ^^^^^

我的代码:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE EmptyDataDecls       #-}
{-# LANGUAGE FlexibleContexts     #-}
{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE GADTs                #-}
{-# LANGUAGE OverloadedStrings    #-}
{-# LANGUAGE QuasiQuotes          #-}
{-# LANGUAGE TemplateHaskell      #-}
{-# LANGUAGE TypeFamilies         #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Main where
import Data.Monoid ((<>))
import Web.Scotty
import qualified Web.Scotty as S
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH 
import Data.Text (Text)
import Data.Time (UTCTime, getCurrentTime)
import qualified Data.Text as T
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Resource (runResourceT, ResourceT)
import Database.Persist.Sql
import Control.Monad (forM_)
import Control.Applicative
import Control.Monad.Logger
import Data.Aeson 
import Data.Default.Class
import GHC.Generics
import Control.Monad.IO.Class (liftIO)

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
ToDo
  title String
  description String
  deriving Show
|]


runDb :: SqlPersist (ResourceT (NoLoggingT IO)) a -> IO a
runDb = runNoLoggingT
    . runResourceT
    . withSqliteConn "todo.db"
    . runSqlConn


instance ToJSON ToDo where
  toJSON(ToDo title description) = object ["title" .= title, "description" .= description]



readToDo :: IO [Entity ToDo]
readToDo = (runDb $ selectList [] [LimitTo 10] )

routes :: ScottyM()
routes = do
  S.get "/hello" $ do
    text "hello world!"
  S.get "/hello/:name" $ do
    name <- param "name"
    text ("hello" <> name <> "!")
  S.get "/todos" $ do
    _ToDo <- liftIO readToDo
    text(_ToDo)

main = do
  putStrLn "Starting server...."
  scotty 7777 routes

如何纠正?

1 个答案:

答案 0 :(得分:0)

似乎编译器指责您在Entity ToDo-s列表和Data.Text.Lazy列表之间进行了错误转换。

请尝试使用 pack 函数手动将其转换:

import Data.Text.Lazy (pack)
...
routes = do
  S.get "/hello" $ do
    text "hello world!"
  S.get "/hello/:name" $ do
    name <- param "name"
    text ("hello" <> name <> "!")
  S.get "/todos" $ do
    _ToDo <- liftIO readToDo
    text(pack . show $ _ToDo)   -- explicit conversion
...