Search code examples
haskellmonadsstate-monad

Efficient implementation of an error log monad


I need a monad which will report error data types (not strings) over the course of a computation. I’ve explored a couple different implementations:

  • A State [Error] a monad where errors are added with cons (:) and at the very end I call reverse on the error list to get the actual order.
  • A Writer (Endo [Error]) a monad where I can add errors with Endo (e :). I’m worried about all the useless concatenation of identity functions, though. If I never add any errors then my Endo will still be a large data structure comprised of many concatenated id . id compositions.
  • A Reader (MVector s Error) (ST s a) monad where I grow the error vector when adding a new error. There isn’t a pre-defined “push” function in the vector package so I’d have to write my own. Also, it would require me to add an ST monad to some of my computations.

In an imperative language, I’d use a vector and call the “push” method or equivalent which would give me amortized O(1) appends and the resulting list would be in the correct order.

What is the most efficient implementation of a Haskell monad (relative to the efficiency of an imperative language) for this task?

Some of my code is in an ST monad and some of my code is pure. I can use different monads for these different use cases. Should I use something different for my ST code than for my pure code?


Solution

  • You should base your logging monad on StateT Seq. Bu using StateT you will have a monad transformer which can overlay your logging functionality on any other monad.

    Some of my code is in an ST monad and some of my code is pure. I can use different monads for these different use cases. Should I use something different for my ST code than for my pure code?

    For the stuff in the ST monad you can use a monad transformer as described above. For pure code things are trickier: you will have to rewrite the pure code as monadic, or at least applicative. At this point it is no longer pure because logging is a side effect. Its hard to advise further because I don't know what you are trying to achieve; it might make more sense to return the logging data from the pure code inside the result type.