Вы, вероятно, захотите использовать 'ReaderT':
type MyMonad a = ReaderT DbHandle ServerPart a
Монадный преобразователь Reader
делает доступным одно значение с помощью функции ask
- в этом случае значение, которое мы хотим, чтобы каждый получилat - это соединение с базой данных.
Здесь DbHandle
- это какое-то соединение с вашей базой данных.
Поскольку 'ReaderT' уже является экземпляром всех типов классов happstack-server, все нормальноВ этой монаде будут работать функции happstack-server.
Возможно, вам также понадобится какой-нибудь помощник для открытия и закрытия соединения с базой данных:
runMyMonad :: String -> MyMonad a -> ServerPart a
runMyMonad connectionString m = do
db <- liftIO $ connect_to_your_db connectionString
result <- runReaderT m db
liftIO $ close_your_db_connection db
(Возможно, лучше использовать функциюкак «скобка» здесь, но я не знаю, есть ли такая операция для монады ServerPart)
Я не знаю, как вы хотите вести журналы - как вы планируете взаимодействовать с вашим журналом-файл?Что-то вроде:
type MyMonad a = ReaderT (DbHandle, LogHandle) ServerPart a
, а затем:
askDb :: MyMonad DbHandle
askDb = fst <$> ask
askLogger :: MyMonad LogHandle
askLogger = snd <$> ask
может быть достаточно.Затем вы можете использовать эти примитивы для создания функций более высокого уровня.Вам также необходимо изменить runMyMonad
для передачи в LogHandle
, что бы это ни было.
Как только вы получите более двух вещей, к которым вы хотите получить доступ, вы получите правильный тип записи вместокортеж.