Haskell's missing mutable reference type
prophet:
But then the question is: are there real functions that look like
libFun? … takes a function fromIO _ -> IO _
Yes, that’s what Fork-fragile reader-like operations in Haskell catalogues. You’ll see a couple of them are even in base. Some of them work directly on IO, some on MonadIO m or MonadUnliftIO m, but …
prophet:
this function has to act on exactly
IO. If you generalized it to work on anymthat implementsMonadIO(OrMonadUnliftIO) … you could instantiatemwithReaderT Logger IO
(MonadIO will not be enough in the general case because it doesn’t allow lifting things like catch, bracket, forkIO, etc.. So, in the general case, we may need as much as MonadUnliftIO.)
Is MonadUnliftIO good enough? Functionally yes, practically no. I address this question in A reference implementation of IOScopedRef. Writing monadic code with an unknown bind is bad for performance, as explained by Alexis King in Effects for Less.
prophet:
You could special case the case where you’re using it with
bracket(which calls its continuation exactly once in a predictable way)
Ah yes, that’s unfortunate. Maybe we could have a Bracket type that abstracts acquire and release. Alternatively, speculatively, a linearly typed continuation?
prophet:
danidiaz:
it’s convenient as an alternative to
ReaderTThe problem is that it’s not an alternative because you still need to pass the
IOScopedRefinto whatever wants to access it
There are many examples in the ecosystem of global, top-level IORefs created with unsafePerformIO. I don’t like that style, but if others do they could do the same with IOScopedRef. (I didn’t describe a newIOScopedRef primitive in the article, but there’s no reason one couldn’t exist. Anyway, it seems from his comment below, @danidiaz doesn’t even want to do that.)
danidiaz:
IIUC, wouldn’t that force you to make
libFunpolymorphic over the monad?
Yes, with the inevitable performance consequences.
Discussion in the ATmosphere