Inserting ErrorT at the base of transformer stack - haskell

What is the best way to run a code with type t (ErrorT String IO) a from within a t IO a monad? Consider the code below:
module Sample where
import System.IO
import Control.Monad.Reader
import Control.Monad.Error
type Env = String
inner :: ReaderT Env (ErrorT String IO) ()
inner = do
s <- ask
fail s
outer :: ReaderT Env IO ()
outer = do
env <- ask
res <- lift $ runErrorT $ runReaderT inner env
case res of
Left err -> liftIO $ hPutStrLn stderr err
Right _ -> return ()
outer
This works, but I've been looking for a more graceful way of inserting ErrorT at the base of my stack. Especially that I'm using several different monad transformer stacks in my project and writing the above for each of them is quite tedious.
I was looking for something like:
outer :: ReaderT Env IO ()
outer = do
res <- (hoist runErrorT) inner
...
But I cannot use hoist due to type mismatch.
Edit:
I use StateT in some of my stacks and that's the reason for trying to put ErrorT at the base and not on the top.
The outer is supposed to be an infinite loop.

Note that as Edward says, it would generally a lot simpler to put the ErrorT at the top of the stack, not the bottom.
This can change the semantics of the stack, at least for more complicated transformers than ReaderT - e.g. if you have StateT in the stack, then with ErrorT at the bottom changes to the state will be rolled back when there's an error, whereas with ErrorT at the top, changes to the state will be kept when there's an error.
If you do really need it at the bottom, then something like this passes the type checker:
import Control.Monad.Error
import Control.Monad.Morph
import System.IO
toOuter :: MFunctor t => t (ErrorT String IO) a -> t IO a
toOuter = hoist runErrorTWithPrint
runErrorTWithPrint :: ErrorT String IO a -> IO a
runErrorTWithPrint m = do
res <- runErrorT m
case res of
Left err -> do
hPutStrLn stderr err
fail err
Right v -> return v
Note that it calls fail when the inner computation fails, which isn't what your code above does.
The main reason is that to use hoist we need to provide a function of type forall a . ErrorT String IO a -> IO a - i.e. to handle any kind of value, not just (). This is because the depending on the rest of the monad stack might mean that the actual return type when you get to the ErrorT is different to the return type you started with.
In the failure case, we don't have a value of type a so one option is to fail.
In your original code you also loop infinitely in outer, which this doesn't do.

The right answer here is "don't do that".
The problem here is you're picking the layering. If you move the Error to the outside it'll behave properly for fail in this situation. In general view the transformer stack as some kind of quantum waveform you shouldn't collapse until the last minute.
inner :: MonadReader Env m => m ()
inner = do
s <- ask
fail s
outer :: (MonadReader Env m, MonadIO m) => m ()
outer = do
res <- runErrorT inner
case res of
Left err -> liftIO $ hPutStrLn stderr err
Right _ -> return ()
outer
Notice how much simpler everything gets. No hoisting, no explicit lifting, nada. inner is run in a different monad where we've extended our current monad whatever it is, with ErrorT on the outside.
By not picking the stack explicitly you maximize the number of situations in which you can use the code.
If you absolutely have to do it, then follow Ganesh's path, but think hard about whether you actually need to morph in the situation you described!

Related

What is the purpose of liftIO?

I have the following code snippet from internet:
calculateLength :: LengthMonad Int
calculateLength = do
-- all the IO operations have to be lifted to the IO monad in the monad stack
liftIO $ putStrLn "Please enter a non-empty string: "
s <- liftIO getLine
if null s
then throwError "The string was empty!"
else return $ length s
and could not understand, why the author use liftIO?
What is the purpose of liftIO?
It is defined as follows:
class (Monad m) => MonadIO m where
-- | Lift a computation from the 'IO' monad.
liftIO :: IO a -> m a
Is it possible to lift IO a -> [a]? It looks like natural transformation.
IO operations like getLine, putStrLn "..." only work inside the IO monad. Using them inside any other monad will trigger a type error.
Still, there are many monads M which are defined in terms of IO (e.g. StateT Int IO, and apparently your LengthMonad as well) and because of that they allow IO actions to be converted into M-actions, and executed as such.
However, we need a conversion for each M:
convertIOintoM1 :: IO a -> M1 a
convertIOintoM2 :: IO a -> M2 a
convertIOintoM3 :: IO a -> M3 a
...
Since this is cumbersome, the library defines a typeclass MonadIO having such conversion function, so that all the functions above can be named liftIO instead.
In practice, liftIO is used each time one wants to run IO actions in another monad, provided such monad allows for it.

throwE and catchE with ExceptT monad on the bottom of monadic stack

Say I have a monadic stack like this:
import Control.Monad.Trans.Reader
import Control.Monad.Trans.Except
import Control.Monad.Trans
type MyMonad = ReaderT Env (ExceptT String IO) -- Env is irrelevant
And a function (simplified, but the idea holds):
f :: Integer -> MyMonad Integer
f 42 = lift $ throwE "42 is an ILLEGAL number"
f n = return n
What I now want to do is call f from another function, but catch the thrown exception if it occurs and somehow handle it (for instance, throw another exception but with the message changed). I'm having a hard time figuring out what kind of lift operations should be done here for it to be done properly. I tried something like this:
g n = do
x <- (f n) `catchE'` (\_ -> lift $ throwE "nope, still illegal")
return x
where catchE' - lift . catchE
but it obviously won't work because catchE' takes something in the ExceptT monad, not MyMonad. Can it be done easily? Perhaps changing the structure of the monad stack could help?
You need more than lift to lift catch through a monad transformer. In fact, there are transformers with no way to lift catch at all (such as ContT). However for ReaderT there is, and the easiest way to make use of that is via Control.Monad.Error.catchError from the mtl library.

What is the best way to manage resources in a monad stack like ExceptT a IO?

For better or for worse, Haskell's popular Servant library has made it common-place to run code in a monad transformer stack involving ExceptT err IO. Servant's own handler monad is ExceptT ServantErr IO. As many argue, this is a somewhat troublesome monad to work in since there are multiple ways for failure to unroll: 1) via normal exceptions from IO at the base, or 2) by returning Left.
As Ed Kmett's exceptions library helpfully clarifies:
Continuation-based monads, and stacks such as ErrorT e IO which provide for multiple failure modes, are invalid instances of this [MonadMask] class.
This is very inconvenient since MonadMask gives us access the helpful [polymorphic version of] bracket function for doing resource management (not leaking resources due to an exception, etc.). But in Servant's Handler monad we can't use it.
I'm not very familiar with it, but some people say that the solution is to use monad-control and it's many partner libraries like lifted-base and lifted-async to give your monad access to resource management tools like bracket (presumably this works for ExceptT err IO and friends as well?).
However, it seems that monad-control is losing favor in the community, yet I can't tell what the alternative would be. Even Snoyman's recent safe-exceptions library uses Kmett's exceptions library and avoids monad-control.
Can someone clarify the current story for people like me who are trying to plow our way into serious Haskell usage?
You could work in IO, return a value of type IO (Either ServantErr r) at the end and wrap it in ExceptT to make it fit the handler type. This would let you use bracket normally in IO. One problem with this approach is that you lose the "automatic error management" that ExceptT provides. That is, if you fail in the middle of the handler you'll have to perform an explicit pattern match on the Either and things like that.
The above is basically reimplementing the MonadTransControl instance for ExceptT, which is
instance MonadTransControl (ExceptT e) where
type StT (ExceptT e) a = Either e a
liftWith f = ExceptT $ liftM return $ f $ runExceptT
restoreT = ExceptT
monad-control works fine when lifting functions like bracket, but it has odd corner cases with functions like the following (taken from this blog post):
import Control.Monad.Trans.Control
callTwice :: IO a -> IO a
callTwice action = action >> action
callTwice' :: ExceptT () IO () -> ExceptT () IO ()
callTwice' = liftBaseOp_ callTwice
If we pass to callTwice' an action that prints something and fails immediately after
main :: IO ()
main = do
let printAndFail = lift (putStrLn "foo") >> throwE ()
runExceptT (callTwice' printAndFail) >>= print
It prints "foo" two times anyway, even if our intuition says that it should stop after the first execution of the action fails.
An alternative approach is to use the resourcet library and work in a ExceptT ServantErr (ResourceT IO) r monad. You would need to use resourcet functions like allocate instead of bracket, and adapt the monad at the end like:
import Control.Monad.Trans.Resource
import Control.Monad.Trans.Except
adapt :: ExceptT ServantErr (ResourceT IO) r -> ExceptT err IO r
adapt = ExceptT . runResourceT . runExceptT
or like:
import Control.Monad.Morph
adapt' :: ExceptT err (ResourceT IO) r -> ExceptT err IO r
adapt' = hoist runResourceT
My recommendation: have your code live in IO instead of ExceptT, and wrap each handler function in a ExceptT . try.

Using returned EitherT in haskell program

I'm trying to use the "citation-resolve" package in a Haskell project I'm working on, but I'm having trouble getting my head around using EitherT's in real code. I get that they're monad transformers, and I think I understand what that means, however I can't seem to actually work out how to use them. The toy example that represents what I'm trying to do is as follows:
module Main where
import Text.EditDistance
import Text.CSL.Input.Identifier
import Text.CSL.Reference
import Control.Monad.Trans.Class
import Control.Monad.Trans.Either
main = do
putStrLn "Resolving definition"
let resRef = runEitherT $ resolveEither "doi:10.1145/2500365.2500595"
case resRef of
Left e -> do
putStrLn ("Got error: "++ e)
Right ref -> do
putStrLn ("Added reference to database: "++ (show ref))
Here, resolveEither has the type:
resolveEither :: (HasDatabase s,
Control.Monad.IO.Class.MonadIO m,
mtl-2.1.3.1:Control.Monad.State.Class.MonadState s m)
=> String -> EitherT String m Reference
and runEitherT $ resolveEither "ref" has the type:
runEitherT $ resolveEither "ref"
:: (HasDatabase s,
Control.Monad.IO.Class.MonadIO m,
mtl-2.1.3.1:Control.Monad.State.Class.MonadState s m)
=> m (Either String Reference)
However, this gives the following error:
Main.hs:10:34:
No instance for (Control.Monad.IO.Class.MonadIO (Either [Char]))
arising from a use of ‘resolveEither’
In the first argument of ‘runEitherT’, namely
‘(resolveEither "doi:10.1145/2500365.2500595")’
In the expression:
runEitherT (resolveEither "doi:10.1145/2500365.2500595")
In an equation for ‘resRef’:
resRef = runEitherT (resolveEither "doi:10.1145/2500365.2500595")
Which I have no idea how to resolve, or work around.
Any help would be appreciated, especially pointers to tutorials dealing with monad transformers from a usage perspective, not an implementation one.
Edit:
To reflect the comments on answers by dfeuer and Christian, I still get errors if I change main to the following:
main = do
putStrLn "Resolving definition"
resRef <- runEitherT (resolveEither "doi:10.1145/2500365.2500595")
case resRef of
Left e -> do
putStrLn ("Got error: "++ e)
Right ref -> do
putStrLn ("Added reference to database: "++ (show ref))
The error I get now is:
No instance for (MonadState s0 IO)
arising from a use of ‘resolveEither’
In the first argument of ‘runEitherT’, namely
‘(resolveEither "doi:10.1145/2500365.2500595")’
In a stmt of a 'do' block:
resRef <- runEitherT (resolveEither "doi:10.1145/2500365.2500595")
In the expression:
do { putStrLn "Resolving definition";
resRef <- runEitherT (resolveEither "doi:10.1145/2500365.2500595");
case resRef of {
Left e -> do { ... }
Right ref -> do { ... } } }
I'm editing my question as well as commenting, as nice code formatting is substantially easier here than in a comment.
I believe the problem is that you're trying to pattern match on resRef when what you probably want to do is execute it and pattern match on the result.
So you should try this:
main = do
putStrLn "Resolving definition"
resRef <- runEitherT $ resolveEither "doi:10.1145/2500365.2500595"
case resRef of
Left e -> do
You've encountered one of the shortcomings of the mtl class-based approach: intimidating type errors. I think it'll be helpful to imagine what the situation would look like with normal transformers-based monad transformers. I hope this will also help you get your feet with monad transformers in general. (It looks like you already understand most of this, by the way; I'm just spelling it out.)
Giving the types is a great way to start. Here's what you had:
resolveEither :: (HasDatabase s,
MonadIO m,
MonadState s m)
=> String -> EitherT String m Reference
There's a type hidden in the constraints, s, which came back to bite you a little later. The constraints, roughly speaking, express the following: s has a database (whatever that means in context); the monad or monad stack m has IO at its base, and somewhere in the monad stack m is a StateT s layer. The simplest monad stack m satisfying those properties would be HasDatabase s => StateT s IO. So we could write this:
resolveEither' :: HasDatabase s
=> String -> EitherT String (StateT s IO) Reference
resolveEither' = resolveEither
All we've done is specify the type of m so it's no longer a variable. We don't need to do that as long as we satisfy the class constraints.
Now it's clearer that there are two layers of monad transformers. Since our main function is in the IO monad, we want to end up with a value of type IO, which we can "run", for instance using <- in do notation. I think of it as "stripping away" layers of the monad transformer, from out to in. (This is what "using" monad transformers boils down to.)
For EitherT, there's a function runEitherT :: EitherT e m a -> m (Either e a). See how the m moves from "inside" the EitherT to "outside"? For me, that's the critical intuitive observation. Similarly for StateT, there's runStateT :: StateT s m a -> s -> m (a, s).
(Incidentally, both are defined as record accessors, which is idiomatic but causes them to show up a bit oddly in Haddock and with the "wrong" type signature; it took me a while to learn to look in the "Constructor" section on Haddocks and mentally add the EitherT e m a -> etc. to the front of the signature.)
So this adds up to a general solution, which you've basically worked out: we need an appropriate value of type s (which I'll call s), then we can use flip runStateT s . runEitherT $ resolveEither "ref" which has type IO ((Either String Reference), s). (Assuming I've kept the types straight in my head, which I probably didn't. I had forgotten flip the first time.) We can then pattern-match or use fst to get to the Either, which seems to be what you really want.
If you'd like me to explicate the errors GHC was giving you, I'd be glad. Informally, it was saying that you weren't "running" or stripping off all the monad transformers. More precisely, it was observing that IO wasn't something like StateT s IO. By using runStateT and runEitherT, you force or constrain the type such that the class constraints end up satisfied. This is kind of confusing when you get things slightly wrong.
Oh, regarding an idiomatic way to write the solution: I'm not sure that a separate retEither function would be idiomatic here, because it looks like it's meddling with global state, i.e. opening some sort of database file. It depends what the library's idiom is like.
Also, by using evalStateT, you're implicitly throwing away the state after evaluation, which may or may not be a bad idea. Does the library expect you to reuse the database connection?
Finally, you have some extra parentheses and some missing type signatures; hlint will help you with those.
Okay, so I think I've worked out a solution to my original problem, which was getting a value of the type IO (Either String Reference) from the function resolveEither (which it does for the resolveDef function it provides).
So, resolveEither returns a type of
(HasDatabase s, MonadIO m, MonadState s m) => String -> EitherT String m Reference
which we can transform to one of type
(HasDatabase s, MonadIO m, MonadState s m) => String -> m (Either String Reference)
using runEitherT . resolveEither. This was where I'd got up to when I asked the question. From there, i tried looking at the source to see how the library extracted a Reference type from the function resolveEither. The library uses the following function:
resolve :: (MonadIO m, MonadState s m, HasDatabase s) => String -> m Reference
resolve = liftM (either (const emptyReference) id) . runEitherT . resolveEither
however, we want to preserve the either, i.e. removing liftM (either (const emptyReference) id)
This however gets us back to where we started, so I looked at the source again, and worked out how this function is used. In the library, the function is used within the following, which transforms the output type of resolve from a value of type (MonadIO m, MonadState s m, HasDatabase s) => m Reference to one of type IO Reference:
resolveDef :: String -> IO Reference
resolveDef url = do
fn <- getDataFileName "default.db"
let go = withDatabaseFile fn $ resolve url
State.evalStateT go (def :: Database)
We can replace resolve in the previous with runEitherT.resolveEither to get a function that returns a IO (Either String Reference):
retEither s = do
fn <- getDataFileName "default.db"
let go = withDatabaseFile fn $ ( (runEitherT.resolveEither) s)
State.evalStateT go (Database Map.empty)
(I've replaced (def :: Database) with (Database Map.empty) as def is only defined internally in citation-resolve)
The overall solution then becomes:
module Main where
import Text.EditDistance
import Text.CSL.Input.Identifier.Internal
import Text.CSL.Input.Identifier
import Text.CSL.Reference
import Control.Monad.Trans.Either
import Control.Monad.State as State
import qualified Data.Map.Strict as Map
main = do
putStrLn "Resolving definition"
resRef <- retEither "doi:10.1145/2500365.2500595"
case resRef of
Left e -> putStrLn ("Got error: "++ e)
Right ref -> putStrLn ("Added reference to database: "++ (show ref))
retEither s = do
fn <- getDataFileName "default.db"
let go = withDatabaseFile fn $ ((runEitherT.resolveEither) s)
State.evalStateT go (Database Map.empty)
Which solves the original problem!
Any pointers on style, or ways of simplifying the whole process would however be very much appreciated.

What is the name of this Monad Stack function?

I've got a bunch of stateful functions inside a State monad. At one point in the program there needs to be some IO actions so I've wrapped IO inside a StateT getting a pair of types like this:
mostfunctions :: State Sometype a
toplevel :: StateT Sometype IO a
To keep things simple I don't want pass the IO context into the main set of functions and I would like to avoid wrapping them in the monad stack type. But in order to call them from the toplevel function I need something akin to a lift, but I'm not trying to lift a value from the inner monad. Rather I want to convert the state in the StateT monad into something equivalent in the State monad. To do this I've got the following:
wrapST :: (State Sometype a) -> StateT Sometype IO a
wrapST f = do s <- get
let (r,s2) = runState f s
put s2
return r
This then get used to interleave things like the following:
toplevel = do liftIO $ Some IO functions
wrapST $ Some state mutations
liftIO $ More IO functions
....
It seems like a fairly obvious block of code so I'm wondering does this function have a standard name, and it is already implemented somewhere in the standard libraries? I've tried to keep the description simple but obviously this extends to pulling one transformer out of a stack, converting the wrapped value to the cousin of the transformer type, skipping the monads below in the stack, and then pushing the results back in at the end.
It may be a good idea to refactor your code to use the type StateT SomeType m a instead of State SomeType a, because the first one is compatible to an arbitrary monad stack. If you'd change it like this, you don't need a function wrapST anymore, since you can call the stateful functions directly.
Okay. Suppose you have a function subOne :: Monad m => State Int Int:
subOne = do a <- get
put $ a - 1
return a
Now, change the types of all functions like this one from State SomeType a to StateT SomeType m a, leaving m as is. This way, your functions can work on any monadic stack. For those functions, that require IO, you can specify, that the monad at the bottom must be IO:
printState :: MonadIO m => StateT Int m ()
printState = do a <- get
liftIO $ print a
Now, it should be possible to use both functions together:
-- You could use me without IO as well!
subOne :: Monad m => StateT Int m ()
subOne = do a <- get
put $ a - 1
printState :: MonadIO m => StateT Int m ()
printState = do a <- get
liftIO $ print a
toZero :: StateT Int IO ()
toZero = do subOne -- A really pure function
printState -- function may perform IO
a <- get
when (a > 0) toZero
PS: I use GHC 7, some of the libs changed midway, so it might be a bit different on GHC 6.
A more direct answer to your question: the function hoist does exactly what you're describing in a slightly more generic way. Example usage:
import Control.Monad.State
import Data.Functor.Identity
import Control.Monad.Morph
foo :: State Int Integer
foo = put 1 >> return 1
bar :: StateT Int IO Integer
bar = hoist (return . runIdentity) foo
hoist is part of the MFunctor class, which is defined like this:
class MFunctor t where
hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b
There are instances for most monad tranformers, but not ContT.

Resources