I'm using the FreeT type from the free library to write this function which "runs" an underlying StateT
:
runStateFree
:: (Functor f, Monad m)
=> s
-> FreeT f (StateT s m) a
-> FreeT f m (a, s)
runStateFree s0 (FreeT x) = FreeT $ do
flip fmap (runStateT x s0) $ \(r, s1) -> case r of
Pure y -> Pure (y, s1)
Free z -> Free (runStateFree s1 <$> z)
However, I'm trying to convert it to work on FT, the church-encoded version, instead:
runStateF
:: (Functor f, Monad m)
=> s
-> FT f (StateT s m) a
-> FT f m (a, s)
runStateF s0 (FT x) = FT $ \ka kf -> ...
but I'm not quite having the same luck. Every sort of combination of things I get seems to not quite work out. The closest I've gotten is
runStateF s0 (FT x) = FT $ \ka kf ->
ka =<< runStateT (x pure (\n -> _ . kf (_ . n)) s0
But the type of the first hole is m r -> StateT s m r
and the type the second hole is StateT s m r -> m r
...which means we necessarily lose the state in the process.
I know that all FreeT
functions are possible to write with FT
. Is there a nice way to write this that doesn't involve round-tripping through FreeT
(that is, in a way that requires explicitly matching on Pure
and Free
)? (I've tried manually inlining things but I don't know how to deal with the recursion using different s
s in the definition of runStateFree
). Or maybe this is one of those cases where the explicit recursive data type is necessarily more performant than the church (mu) encoding?