Is there any "standard" way to utilize the equivalence of Reader and a normal function?
haskell
Solution
You can simply use the fact that the function monad `(->) r` already has an instance for `MonadReader r` defined in `Control.Monad.Reader`. You can write functions using just the `MonadReader` constraint and use them either as normal functions or in other `ReaderT` monads:
f :: MonadReader Int m => m Int
f = do
a <- ask
return $ 2 * a + 3 * a
normally :: Int
normally = f 1
-- normally == 5
readerly :: Reader Int Int
readerly = do
result <- f
return $ 2 * result
> runReader f 1
5
> runReader readerly 1
10
Problem
I am writing a framework, where the main function asks user about the function of type `a -> [b]`. However, because that function can be quite complex, its implementation can often look like this: ``` fn a = extractPartOfAAndConvert a ++ extractAnotherPartofAAndConvert a ``` That's why I figured using `Reader` might be a nice, idiomatic idea to fight that. However, at the same time I realize that some people might not want to use a monad. While experimenting, I've crafted this solution: ``` class Iso a b where isoFrom :: a -> b isoTo :: b -> a instance Iso a a where isoFrom = id isoTo = id instance Iso (a -> b) (Reader a b) where isoFrom f = reader f isoTo m = runReader m ``` Which in turn allows me to do: ``` testCallback :: MyState -> Callback -> MyState testCallback myState cb = cb myState -- The important signature testCallbackGeneric :: Iso Callback a => MyState -> a -> MyState testCallbackGeneric myState cb = (isoTo cb) myState callbackFunction :: Callback callbackFunction s = s + 10 callbackMonad :: Reader MyState MyState callbackMonad = do x <- ask return $ x - 10 ----------- let myStateA = testCallback myState callbackFunction -- let myStateB = testCallback myState callbackMonad -- won't work, obviously let myStateC = testCallbackGeneric myState callbackFunction let myStateD = testCallbackGeneric myState callbackMonad ``` However, I feel very much like I'm reinventing the wheel. Is there a way to express the equivalence of Reader to easily write such generic functions without resorting to creating my own type class?