1
votes

I'm new in Haskell. I woudl like to create simple crud rest api with scotty and persistence. I'm using sqlite with one table todo (title text, description text), I have some records in table. My point is to show all records on enpoint /todos in json format. When I print it I gets an error

  • 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)
   |          ^^^^^

My code:

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

How to correct this?

1

1 Answers

0
votes

It looks like compiler accused you of having a bad conversion between the list of Entity ToDo-s and Data.Text.Lazy.

Please try to convert it by hand using pack function:

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
...