Open Icelandjack opened 3 years ago
I'm using Codensity
to ensure timely resource cleanup (like a transformer version of the managed
library), in which case this is not going to be the instance you want, since it will run your finalizers early, as you exit the mdo
block.
Another option is to use a lazily-evaluated promise for the result, mirroring the approach in fixIO
:
fixCodensity :: MonadIO m => (a -> Codensity m a) -> Codensity m a
fixCodensity f = Codensity \k -> do
promise <- liftIO $ IORef.newIORef (error "result eval'd too early")
ans <- liftIO $ unsafeDupableInterleaveIO (IORef.readIORef promise)
runCodensity (f ans) \a -> do
liftIO $ IORef.writeIORef promise a
k a
This is also probably not the instance you'd want in a general-purpose library, but I figured I'd put it here for reference.
There's also an implementation here: https://stackoverflow.com/questions/25827227/why-cant-there-be-an-instance-of-monadfix-for-the-continuation-monad
instance MonadFix m => MonadFix (Codensity m) where
mfix f = Codensity (\ka -> mfixing (\a -> runCodensity (f a) ka<&>(,a)))
where mfixing f = fst <$> mfix (\ ~(_,a) -> f a )
The library mmtl has a
MonadFix (Codensity m)
instancehttps://hackage.haskell.org/package/mmtl-0.1/docs/Control-Monad-Codensity.html