Hello all, (solution)
I have purescript module that I’m out of ideas why it is not working, problem is function
executeWithConnection :: Either String Form -> Either PGError Connection -> Aff (Either String (Maybe PGError))
executeWithConnection eitherBodyParams eitherConn = do
input <- prepareValues eitherConn eitherBodyParams
pure $ executeQueries input
problem I get is
Error found:
in module Main
at src/Main.purs:115:3 - 115:53 (line 115, column 3 - line 115, column 53)
Could not match type
Either String
with type
Aff
while trying to match type Either String t0
with type Aff (Either String (Maybe PGError))
while checking that expression (bind ((prepareValues eitherConn) eitherBodyParams)) (\input ->
(apply pure) (executeQueries input)
)
has type Aff (Either String (Maybe PGError))
in value declaration executeWithConnection
where t0 is an unknown type
See https://github.com/purescript/documentation/blob/master/errors/TypesDoNotUnify.md for more information,
or to contribute content related to this error.
I was triing add/remove pure in function but it did not worked out, whole file is like this
module Main where
import Prelude (Unit, (==), ($), bind, show, pure, discard, (<>), flip)
import Control.Monad.Indexed.Qualified as Ix
import Control.Monad.Reader (ReaderT, asks, runReaderT)
import Control.Monad.Reader.Class (class MonadAsk)
import Data.Number as Number
import Data.Maybe (Maybe(Just))
import Data.Either (Either(Right, Left))
import Data.HTTP.Method (Method(GET, POST))
import Data.Bifunctor (rmap, lmap)
import Effect (Effect)
import Effect.Aff (Aff)
import Effect.Class.Console (logShow)
import Hyper.Middleware (lift', Middleware)
import Hyper.Node.Server (defaultOptionsWithLogging, runServer', HttpRequest, HttpResponse)
import Hyper.Response (closeHeaders, respond, writeStatus, StatusLineOpen, ResponseEnded)
import Hyper.Request (getRequestData)
import Hyper.Status (Status, statusOK, statusBadRequest)
import Hyper.Form (Form, parseForm, required)
import Hyper.Conn (Conn)
import Text.Smolder.HTML (Html, html, p, form, label, input, button, div)
import Text.Smolder.HTML.Attributes (method, for, id, name, type')
import Text.Smolder.Markup (text, (!))
import Text.Smolder.Renderer.String (render)
import Database.PostgreSQL (Pool, PoolConfiguration, Connection, PGError, newPool, withConnection, execute, defaultPoolConfiguration, Row3(Row3), Query(Query))
type ComponentsType = Record ()
type ConnHttp resp = Conn HttpRequest (HttpResponse resp) ComponentsType
type Env =
{ pool :: Pool
}
type AppM m = ReaderT Env m
getPool :: forall m. MonadAsk Env m => m Pool
getPool = asks _.pool
runAppM ∷ forall a. Env -> (AppM Aff a) -> Aff a
runAppM = flip runReaderT
config :: PoolConfiguration
config =
let default = defaultPoolConfiguration "purescript"
in default
{ host = Just "localhost"
, password = Just "postgres"
, user = Just "postgres"
}
send :: Status -> Html Unit -> Middleware (AppM Aff) (ConnHttp StatusLineOpen) (ConnHttp ResponseEnded) Unit
send status body = Ix.do
writeStatus status
closeHeaders
respond (render body)
greetTemplate :: String -> Html Unit
greetTemplate name = html (p (text $ "Hello " <> name))
formTemplate :: Html Unit
formTemplate =
html do
form ! method "post" $ do
label ! for "name" $ text "Name"
input ! id "name" ! name "name"
button $ text "Greet"
fruitForm :: Html Unit
fruitForm =
html do
form ! method "post" $ do
div do
label ! for "name" $ text "Name"
input ! id "name" ! name "name"
div do
label ! for "delicious" $ text "Delicious"
input ! id "delicious" ! name "delicious" ! type' "checkbox"
div do
label ! for "price" $ text "Price"
input ! id "price" ! name "price" ! type' "number"
button $ text "Save"
errorTemplate :: String -> Html Unit
errorTemplate error = html do
p (text error)
formHandler :: Middleware (AppM Aff) (ConnHttp StatusLineOpen) (ConnHttp ResponseEnded) Unit
formHandler = send statusOK formTemplate
fruitNewHandler :: Middleware (AppM Aff) (ConnHttp StatusLineOpen) (ConnHttp ResponseEnded) Unit
fruitNewHandler = send statusOK fruitForm
fruitCreateHandler :: Middleware (AppM Aff) (ConnHttp StatusLineOpen) (ConnHttp ResponseEnded) Unit
fruitCreateHandler = Ix.do
eitherBodyParams <- parseForm
result <- lift' $ do
logShow "Staring"
pool <- getPool
withConnection pool (executeWithConnection eitherBodyParams)
badRequestHandler "Success"
executeWithConnection :: Either String Form -> Either PGError Connection -> Aff (Either String (Maybe PGError))
executeWithConnection eitherBodyParams eitherConn = do
input <- prepareValues eitherConn eitherBodyParams
pure $ executeQueries input
prepareValues :: (Either PGError Connection) -> (Either String Form) -> Either String {conn :: Connection, name :: String, delicious :: String, price :: String}
prepareValues eitherConn eitherBodyParams = do
conn <- lmap show eitherConn
params <- eitherBodyParams
name <- required "name" params
delicious <- required "delicious" params
price <- required "price" params
pure {conn, name, delicious, price}
executeQueries :: {conn :: Connection, name :: String, delicious :: String, price :: String} -> Aff Unit
executeQueries {conn, name, delicious, price} =
let
query = Query "INSERT INTO fruits (name, delicious, price) VALUE ($1, $2, $3)"
row = (Row3 name (castBoolean delicious) (Number.fromString price))
in do
result <- execute conn query row
logShow result
castBoolean :: String -> Boolean
castBoolean value = value == "on"
badRequestHandler :: String -> Middleware (AppM Aff) (ConnHttp StatusLineOpen) (ConnHttp ResponseEnded) Unit
badRequestHandler message = send statusBadRequest (errorTemplate message)
postHandler :: Middleware (AppM Aff) (ConnHttp StatusLineOpen) (ConnHttp ResponseEnded) Unit
postHandler = Ix.do
bodyData <- parseForm
case bodyData of
Right params -> case required "name" params of
Right name -> send statusOK (greetTemplate name)
_ -> badRequestHandler "Missing name"
_ -> badRequestHandler "Invalid Body"
handler :: Middleware (AppM Aff) (ConnHttp StatusLineOpen) (ConnHttp ResponseEnded) Unit
handler = Ix.do
requestData <- getRequestData
case requestData.url of
"/fruits" ->
case requestData.method of
Left GET -> fruitNewHandler
Left POST -> fruitCreateHandler
_ -> badRequestHandler "Unsupported method"
_ ->
case requestData.method of
Left GET -> formHandler
Left POST -> postHandler
_ -> badRequestHandler "Unsupported method"
main :: Effect Unit
main = do
pool <- newPool config
runServer' defaultOptionsWithLogging {} (runAppM { pool: pool }) handler
any ideas? Thank you in advance