Hacker News new | past | comments | ask | show | jobs | submit login

> 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 ...



Your two datatypes are representationally equal. So would be very surprised by handrolling the datatype maling any difference. The instance however might make more sense


Indeed. The folklore I heard is that you can get performance gains because with the handrolled version, GHC is able to inline the instance dictionaries.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: