3 ms·
> Converting them to a cleaner ReaderT led to a 10% total run time regression, so I had to revert it. It makes me wonder about the speed penalty of code I desig
by endgame 7y ago
> Converting them to a cleaner ReaderT led to a 10% total run time regression, so I had to revert it. It makes me wonder about the speed penalty of code I designed better to begin with.
I have heard from other Haskellers that you can sometimes get good performance by hand-rolling an application monad, and then writing out the MonadFoo instances so you get good ergonomics:
-- Instead of this:
newtype App a = App { runApp :: ReaderT AppEnv (ExceptT AppError IO) a }
deriving (Functor, Applicative, Monad, MonadIO, MonadReader AppEnv, MonadError AppError)
-- Try this:
newtype App a = App { runApp :: AppEnv -> IO (Either AppError a) } deriving Functor
instance Applicative App where ...
instance Monad App where ...
instance MonadIO App where ...
instance MonadReader AppEnv App where ...
instance MonadError AppError App where ...
- arianvanp 7y agoYour two datatypes are representationally equal. So would be very surprised by handrolling the datatype maling any difference. The instance however might make more sense
- endgame 7y agoIndeed. The folklore I heard is that you can get performance gains because with the handrolled version, GHC is able to inline the instance dictionaries.