Функция, которая возвращает значение ContextT
(здесь заключено в Processor
), например start
, не должна вызывать GP.runContextT
.
GP.runContextT
.инициализировать и предоставлять контекст для выполнения процессоров, что вы хотите сделать только один раз в начале всей программы.Таким образом, он, вероятно, должен быть в main
, вместе с newWindow
, defaultWindowConfig
и mkFullState
.
A Processor
подобно start
можно получить текущее состояние с помощью преобразователя StateT
,Но сначала мы должны исправить тип Processor
.Обратите внимание на тип runContextT
, в частности forall
:
runContextT
:: (MonadIO m, MonadAsyncException m, ContextHandler ctx)
=> ContextHandlerParameters ctx -> (forall os. ContextT ctx os m a) -> m a
. Это forall
означает, что переменная типа os
не может встречаться в m
или в a
, предотвращаяопределенные ресурсы от утечки.Это несовместимо с текущим определением Processor
, поскольку StateT (FullState os) IO
содержит os
.Возможно, вы можете поменять местами трансформаторы.
newtype Processor ctx os a = Processor {
runProcessor :: StateT (FullState os) (GP.ContextT ctx os IO) a
}
Теперь start
может использовать get
для доступа к текущему состоянию, и, поскольку он не должен обрабатывать инициализацию, он не имеет Quit
ветвление больше (вы можете больше не хотеть делать start
a Processor
на данный момент, но, надеюсь, это достаточно близко к тому, что вы на самом деле хотели бы сделать с другими процессорами):
start :: Processor ctx os (Transition os)
start = Processor $ do
s <- get
return $ ToMainMenu s
И main
может выглядеть так:
main :: IO ()
main =
-- Initialize and provide context, i.e, convert the wrapped
-- do-block of type `ContextT _ _ IO` to `IO`
GP.runContextT GLFW.defaultHandleConfig $ do
-- Create a GLFW window
-- You can probably create more than one
win <- GP.newWindow (GP.WindowFormatColor GP.RGB8) (GLFW.defaultWindowConfig "Foobar")
-- Create the initial processor state, handling initialization failures
s_ <- liftIO $ runExceptT $ mkFullState win "./"
s0 <- case s_ of
Left e -> fail e
Right s0 -> return s0
-- Run a processor
(transition, s1) <- (`runStateT` s0) $ runProcessor start
case transition of
Quit -> return ()
ToMainMenu _ -> return ()