In a Free monad interpreter using iterT, I'd like to have an internal state, but I'm not sure how to do so since the iterT function provides the continuation f pre-loaded with the recursive call, as I understand it. I suppose a StateT wrapper is a possible solution (?) but it would be nice to avoid if possible. Thanks.
Edit: To clarify, the internal state is the mval parameter passed to the inner func. I'd like to allocate a resource and continue the interpreter with the resource.
import Control.Monad.Trans.Free.Church
import Control.Monad.Free.TH
type SomeFree m = FT SomeFreeF m
data SomeFreeF next = SomeAct (() -> next)
deriving instance (Functor SomeFreeF)
makeFree ''SomeFreeF
runSomeFree :: SomeFree IO () -> IO ()
runSomeFree = inner Nothing
where
inner mval =
iterT \case
SomeAct f -> do
case mval of
Nothing -> do
a <- init
inner (Just a) (FT someAct f ??)
-- How to continue the inner loop with
-- the new state and the continuation `f`?
Just a -> do
f a
As I noted in the comments, at first blush this seems like a job for
iterTM, which is likeiterTexcept it runs in the monad transformer of your choice.You get to pick the output monad
t, butmandaare defined by theFreeTdata structure you're folding up. For each layer of theFreeT, starting at the bottom,iterTMpasses anffull of the results of folding the layer's children into your callback. You get to decide how to process those monadic results (pick between them, sequence them, whatever).You mentioned running your fold in a
StateT, but the example code you've given looks more likeReaderTto me. (You're not returning a modified state from each iteration - just passing a modified parameter downwards.)