Ok, so I have figured out how to implement Reader
(and ReaderT
, not shown) using the operational
package:
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
import Control.Monad.Operational
data ReaderI r a where
Ask :: ReaderI r r
type Reader r a = Program (ReaderI r) a
ask :: Reader r r
ask = singleton Ask
runReader :: forall r a. Reader r a -> r -> a
runReader = interpretWithMonad evalI
where evalI :: forall b. ReaderI r b -> (r -> b)
evalI Ask = id
But I can't figure out for my life how to do this with free monads (I'm using Edward Kmett's free
package). The closest I've gotten is this, which I understand is cheating (something about how ((->) r)
is already a monad):
import Control.Monad.Free
type Reader r a = Free ((->) r) a
ask :: Reader r r
ask = Free Pure
runReader :: Reader r a -> r -> a
runReader (Pure a) _ = a
runReader (Free k) r = runReader (k r) r
-- Or, more simply and tellingly:
--
-- > runReader = retract
Even if this wasn't as dumb as I suspect it is, it's not what I want because what I want, basically, is to be able to inspect a Reader
as data...