Я создаю Haskell Servant
API, используя библиотеку SQL под названием Squeal
: https://github.com/morphismtech/squeal
Мне нужна помощь в корректировке типов, чтобы приложение скомпилировалось.
Моя Схема имеет тип
type Schema = '["users" ::: UsersTable, ...]
type Schemas = Public Schema
Где Public
— это семейство типов для базы данных с одной схемой. Это взято с: http://hackage.haskell.org/package/squeal-postgresql-0.5.1.0/docs/Squeal-PostgreSQL-Schema.html
Я пытаюсь передать пул соединений в Reader следующим образом:
import qualified Squeal.PostgreSQL as S
import qualified Squeal.PostgreSQL.Pool as SPG
newtype AppT m a
= AppT
{ runApp :: ReaderT SquealPool (ExceptT ServerError m) a
} deriving
( Functor, Applicative, Monad, MonadReader SquealPool, MonadError ServerError
, MonadIO
)
type App = AppT IO
type SquealPool = SPG.Pool (SQ.K S.Connection Schema)
Мой SQL-запрос и сеанс выглядят примерно так:
emailQuery :: Query_ Schemas (Only Text) UserEmail
emailQuery = select (#email `as` #email)
(from (table #users) & where_ (#email .== param @1))
emailTakenSession
:: (MonadReader SquealPool m, MonadPQ Schemas m, MonadIO m)
=> Text
-> m UserEmail
emailTakenSession email = do
result <- runQueryParams emailQuery (Only email)
email <- getRow 1 result
return email
Наконец, я использую их в обработчиках Servant
следующим образом:
emailTaken :: MonadIO m => Text -> AppT m APIEmail
emailTaken emailStr = do
pool <- ask -- this produces error
result <- liftIO $ runPoolPQ (Q.emailTakenSession emailStr) pool
return $ APIEmail result True
Проблема
Компилятор сообщает об ошибке в ask
в emailTaken
:
* Couldn't match kind `[(ghc-prim-0.5.3:GHC.Types.Symbol,
Squeal.PostgreSQL.Schema.SchemumType)]'
with `Squeal.PostgreSQL.Schema.SchemumType'
Насколько я понимаю, он пытается сопоставить семейство типов Schemas
с типом Schema
.
Вопрос
Как мне нужно отредактировать сигнатуры типов, чтобы это скомпилировалось и работало? В частности, emailTakenSession
, вероятно, по крайней мере выключен.
Решение
В интересах полноты для других читателей мне нужно было изменить
type SquealPool = SPG.Pool (SQ.K S.Connection Schema)
в
type SquealPool = SPG.Pool (S.K S.Connection '["public" ::: Schema])
Семейство типов в любом случае разрешит это, и таким образом я не предоставляю недопустимую конструкцию (семейство типов) для наследования MonadReader в AppT
.