DEV Community

Moremi Vannak
Moremi Vannak

Posted on

10 4

Difference between monad-transfomer, mtl, and mtl-style technique

This post is mean to explain the differences between the 3. These 3 terms come up regularly and it is important to differentiate them.

Requirement

This post aims for the pre-intermediate haskell programmers that have already learn the fundamental concept (monad, functor ...) and have written some haskell program already.

Monad Transformer

monad-transformer is a type container such as ReaderT, WriterT ... We will focus on the use-case only.

When people refer to monad-transformer they usually mean something their monad-transformer stack: newtype AppM a = ReaderT Env (LoggingT IO) a

The reason why haskell application use this stack over just IO () because monad-transformer provide extra functionality for example ReaderT provide ask function to get env variable instead of passing it in all the functions.

MTL - Monad Transformer Library

mtl library define various typeclasses that help working with monad-transformer. Remember that mtl is a library not a monad-transformer.

The reason why mtl is created because when we define a function to work with monad-transformer stack, we do not want to use AppM in the function type.

For example:

  • instead of this askEnvAndReadFile :: FilePath -> AppM String
  • we want to use this askEnvAndReadFile :: (MonadReader Env m, MonadIO m) -> FilePath -> m String

MonadReader and MonadIO are typeclasses that show that the function can ask for Env and can do IO action. This function can be use within any monad-trasnformer stack that has ReaderT and IO in them, not just our predefined AppM.

MTL-style (tagless final)

Sometimes when mtl is being discussed, it is not about the mtl library itself but the techniques that mtl library uses which is the Tagless Final. I will not provide detail explanation of this, but basically this is a technique that help haskell programmer write function with business model constraint.

For example, we want to define a function that can manage certain resources (make api call to get the resources). We do not want the function to be able to do any IO action.
Below show a function that can only make http call and log, not any other action

app :: (ManageResource m, HasLogging m) -> m ()
app = do
    result <- makeApiCall
    log (show result)
    pure ()

Notice that ManageResource and HasLogging is a typeclass that has nothing to do with mtl library, but instead we define this by ourself:

class (Monad m) => ManageResource m where
  makeApiCall :: m Resource

This is just an interface only, the implementation makeApiCallIO will have MonadIO constraint or return IO monad: makeApiCallIO :: IO Resource).
So when we want to use this function with our stack AppM we can define an instance for this ManageResource typeclass.

instance ManageResource AppM where
  makeApiCall = makeApiCallIO

The useful thing of using typeclass constraints instead of concrete type such as AppM is that we can use a mock stack MockM where we do not actually do any IO action.

Example:

makeApiCallMock :: m Resource
makeApiCallMock = pure someMockData

instance ManageResource MockM where
  makeApiCall = makeApiCallMock

Conclusion

As we can see, the 3 terms are different. The most important thing is the mtl-style technique that is used a lot in realworld haskell application (HasDatabase, HasLogging ...). It is important to be able to read other people constraint typeclasses as well as create our own. I was confused to this 3 terms as well before, hope this clears up some misunderstanding.

Detail Source:

  1. https://serokell.io/blog/2018/12/07/tagless-final
  2. https://ocharles.org.uk/posts/2016-01-26-transformers-free-monads-mtl-laws.html

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay