0

I use shake but the operations I call are in an ErrIO and not in the IO monad. How can I lift such operations into the Action monad. I could runErr and get and Either value and then call throwIO or liftIO (depending on the result). Is this the recommended approach?

The code could be like:

runErr2action :: ErrIO a -> Action a
runErr2action op = liftIO $ do
    res <- runErr  op
    case res of
        Left msg -> throw msg
        Right a -> return a

Perhaps connected question: Why is there no instance of MonadError for Action?

user855443
  • 2,596
  • 3
  • 25
  • 37
  • Do you mean Action rather than Accum? If not, can you link to Accum? – Neil Mitchell Feb 09 '19 at 09:34
  • Sorry, I was confusing Action with something I was reading on when I wrote the question. I fixed the question and added draft code. Thank you for tyour attention! – user855443 Feb 09 '19 at 10:37

1 Answers1

0

A Shake rule is expected to either succeed producing the result it promised, or fail. In most cases, anything that it calls producing a Left or failure value should be turned into an exception, using throw/error (or ideally variants in IO with liftIO, so the exception happens at a specific point not based on evaluation order). However, there are a few cases where a sub-action failing might not fail the rule, e.g.:

  1. Perhaps you are running a test, and the test failing is a valid and correct output that you handle in some well defined manner, by recording the failure. In many cases such a failure would be detected at a higher level.
  2. Perhaps you have two ways to build something, and the Either indicates the first way failed, so you should try the second method.

As to why there's no MonadError instance for Action, the main reason is that there are a few MonadError type classes, and Shake doesn't depend on any of the libraries providing them, so it would introduce an additional dependency. It also wouldn't offer any significant benefit over error or liftIO . throwError.

Neil Mitchell
  • 9,090
  • 1
  • 27
  • 85