Мне нравилось изучать Haskell, и я думаю, что достиг хороших успехов с помощью людей здесь и в #haskell. Мое обучение в основном все еще происходит на том этапе, когда я смотрю на примеры и пытаюсь абстрагироваться от применяемых там методов и применять их к своему собственному коду.
В настоящее время я начал изучать разработку стеков монад для различных приложений и хочу включить в свое приложение функциональность персистентного фреймворка.
Вот мой стек монад:
newtype App a = App { unApp :: StateT AppState (SqlPersistT (ResourceT (LoggingT IO))) a }
deriving ( Applicative
, Functor
, Monad
, MonadIO
, MonadState AppState
)
AppState
— это просто тип данных записи, содержащий одно значение Int в этом примере.
Моя основная функция выглядит так:
main = runApp "./test.sqlite" (AppState 69) runMigrate
где runApp
должен развернуть все монады:
runApp :: Text -> AppState -> App a -> IO a
runApp t s a =
runStdoutLoggingT . runResourceT . withSqliteConn t . runSqlConn . flip evalStateT s . unApp
а runMigrate
— это приложение для запуска в монаде App
. В этом случае я стремился просто заставить его запустить миграцию:
runMigrate :: App ()
runMigrate = return $ liftPersist $ runMigration migrateAll
Компилятор указывает, что я не знаю, что делаю с жалобой:
Main.lhs:59:16:
Couldn't match type ‘m0 ()’ with ‘()’
Expected type: App ()
Actual type: App (m0 ())
In the expression: return $ liftPersist $ runMigration migrateAll
In an equation for ‘runMigrate’:
runMigrate = return $ liftPersist $ runMigration migrateAll
Вопросы:
Как правильно это сделать?
Что произойдет, если я введу в свой стек монад
ReaderT
? Учитывая, чтоSqlPersistT
на самом деле являетсяReaderT
, как я могу убедиться, чтоask
соответствует реальномуReaderT
, а неSqlPersistT
?