1. 7

In the GMane discussion linked, click the subject to see the thread of replies.

  1.  

  2. 5

    It’s worth noting that this is from 2007. Today, 2 and 3 are the same, 5, 6, and 7 might be better replaced by the exceptions package. Possibly 8, too, but some don’t like mtl style classes.

    4 is just wrong. So wrong. Do not use four. This article give bad advice here.

    And finally, 1 is a special kind of thing that should probably not be considered in the same sentence as the rest. It’s probably something you should never use, but it’s sometimes used to indicate errors in mature libraries when those errors should never, ever happen. A good example is using error to ignore a case match which is known to be impossible due to a non-typechecked invariant in your library and you know your library is bug free.

    1. 1

      4 is just wrong. So wrong. Do not use four. This article give bad advice here.

      Why is that? I know basic Haskell, but not really any of the conventions, and that method seemed to make the most sense to me.

      1. 3

        It’s pretty universally thought to be the case that including fail as a method of Monad was a mistake. As it turns out there are plenty of useful monads which have no notion of fail. When you implement such a monad you still must implement fail and therefore you usually do something like

        instance Monad (Reader e) where
          return a = Reader (\e -> a)
          Reader f >>= k = Reader (\e -> runReader (k (f e)) e)
          fail msg = Reader (\e -> error "Failure")
        

        That error is pretty much the only option available to you and since it’s semantically meaningless and difficult to catch… it just makes for some bad times.

        So if you frequently use code which has a type like Monad m => ... m a ... and you make use of the fail method that constraint gives you then it’s very easy that you’ll end up one day accidentally applying it to a monad which has a pathological fail method and you’ll get a very difficult to trace bug.

        On the other hand, if you use something from exceptions your previous type will look like MonadThrow e m => ... m a ... and you’ll be much more prepared to find that thrown error.