Is there a “standard” way to use Reader equivalence and normal function?

I am writing a framework where the main function asks the user for a function like a -> [b] .

However, since this function can be quite complex, its implementation may look something like this:

 fn a = extractPartOfAAndConvert a ++ extractAnotherPartofAAndConvert a 

That's why I thought using Reader might be a nice idiomatic idea to deal with this. However, at the same time, I understand that some people may not want to use a monad.

During the experiments, I developed this solution:

 class Iso ab where isoFrom :: a -> b isoTo :: b -> a instance Iso aa where isoFrom = id isoTo = id instance Iso (a -> b) (Reader ab) where isoFrom f = reader f isoTo m = runReader m 

This, in turn, allows me to:

 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 really feel like I'm reinventing the wheel.

Is there a way to express Reader equivalence in order to easily write such general functions without resorting to creating my own type class?

+7
haskell
source share
1 answer

You can simply use the fact that the monad (->) r function already has an instance for MonadReader r defined in Control.Monad.Reader . You can write functions using only the MonadReader restriction and use them either as regular 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 
+10
source share

All Articles