Search code examples
apihaskellmonad-transformers

Transformers in type signature or not?


Just thinking about an API design. What is "common" in Haskell? Transformers in type signature or rather "hidden"?

findById :: ID -> IO (Maybe User)
findById x = runMaybeT $ do
  ...
  return User

or

findById :: ID -> MaybeT IO User
findById x = do
  ...
  return User

Solution

  • If this is for something simple, and it's only a few functions that do this maybe-in-IO, I would just make the type IO (Maybe User).

    If this is a pattern that stretches across your library, I would give a semi-abstract name to the tfm-stack monad:

    type Request = MaybeT IO
    
    findById :: ID -> Request User
    

    ... or even

    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    newtype Request a = Request (runRequest :: MaybeT IO a)
       deriving (Functor, Applicative, Monad)
    

    Making the signature ID -> MaybeT IO User isn't very good: the transformer only helps if you're doing a whole bunch of actions in that monad, but in that case always writing out MaybeT IO violates the DRY principle.