3 ms·
I've seen them created a few times. I'm pretty sure there are at least a few implementations in Hackage of such divided IO monads. More generally, the haute met
by tel 14y ago
I've seen them created a few times. I'm pretty sure there are at least a few implementations in Hackage of such divided IO monads. More generally, the haute method for solving this would be to use Operational or Free monads to create your restricted monad type and then interpret it into IO.
http://www.haskellforall.com/2012/07/purify-code-using-free-monads.html http://www.haskellforall.com/2012/07/purify-code-using-free-...
http://www.haskellforall.com/2012/06/you-could-have-invented-free-monads.html http://www.haskellforall.com/2012/06/you-could-have-invented...
- dllthomas 14y agoI think optimally, with a set of typeclasses, one could define instances for IO and just use things with no interpretation or build a datastructure with free monads to perform whatever other inspections or manipulations you want. There could be some incompatability between the two notions that I'm missing, though...
- tel 14y agoI think I've seen the typeclass route as well before. It may have just been a blog post and not a library implementation, though. The two methods have different epistemological ideas, but could be combined. For instance: {-# LANGUAGE DeriveFunctor, GeneralizedNewtypeDeriving, FlexibleInstances #-} module CrWr where import Control.Monad.Free import Data.IORef data RWRefF t a = NewRef t (IORef t -> a) | PeekRef (IORef t) (t -> a) | PutRef (IORef t) t a deriving Functor newtype RWRef t a = RWRef (Free (RWRefF t) a) deriving Monad newRef :: t -> RWRef t (IORef t) newRef t = RWRef $ liftF $ NewRef t id peekRef :: IORef t -> RWRef t t peekRef r = RWRef $ liftF $ PeekRef r id putRef :: IORef t -> t -> RWRef t () putRef r t = RWRef $ liftF $ PutRef r t () interpret :: RWRef t a -> IO a interpret (RWRef (Pure a)) = return a interpret (RWRef (Free (NewRef t f))) = newIORef t >>= interpret . RWRef . f interpret (RWRef (Free (PeekRef r f))) = readIORef r >>= interpret . RWRef . f interpret (RWRef (Free (PutRef r t next))) = writeIORef r t >> interpret (RWRef next) -- Highly specialized class of IO monads class Monad m => RWIntRefMonad m where new :: Int -> m (IORef Int) peek :: IORef Int -> m Int put :: IORef Int -> Int -> m () toIO :: m a -> IO a instance RWIntRefMonad (RWRef Int) where new = newRef peek = peekRef put = putRef toIO = interpret incr :: RWIntRefMonad m => IORef Int -> m () incr r = peek r >>= put r . (+1) main = do r <- newIORef 0 -- We need to specialize before the m gets erased toIO (incr r :: RWRef Int ()) readIORef r >>= print