ErrorT binding function - haskell

newtype ErrorT e m a = ErrorT { runErrorT :: m (Either e a) }
instance (Monad m, Error e) => Monad (ErrorT e m) where
m >>= k = ErrorT $ do
a <- runErrorT m
case a of
Left l -> return (Left l)
Right r -> runErrorT (k r)
ErrorT is just a value constructor ( type constructor as well) and to get instance of that type ( to get ErrorT value ) we have to call constructor with one parameter- a function ( destructor) which gets ErrorT and returns inner monad, in our case it is any m (Either e a). So, in bind function it is defined: m >>= k = ErrorT $ .... But, in its definion it calls runErrorT which is just definied. So something like recursive call. But, I suppose that there is no recursion here. That means that I misunderstand something with monad/ monad transformers. Please help :)

I think you are confused by the newtype wrapper. The newtype definition of ErrorT results in two functions being defined:
ErrorT :: m (Either e a) -> ErrorT e m a
runErrorT :: ErrorT e m a -> m (Either e a)
so in the definition of (>>=), ErrorT $ do ... refers to the constructor for the ErrorT newtype while
a <- runErrorT m
runErrorT (k r)
refer to the 'unwrapping' function to extract the underlying m (Either e a).

Related

argument of runMaybeT of MaybeT

In https://en.wikibooks.org/wiki/Haskell/Monad_transformers, I see
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
and then the instanciation of MaybeT as a monad:
instance Monad m => Monad (MaybeT m) where
return = MaybeT . return . Just
-- The signature of (>>=), specialized to MaybeT m:
-- (>>=) :: MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b
x >>= f = MaybeT $ do maybe_value <- runMaybeT x
case maybe_value of
Nothing -> return Nothing
Just value -> runMaybeT $ f value
I do not understand the arg x in runMaybeT x. Shouldn't runMaybeT take an arg corresponding to a? But instead it is given x which is the entire MonadT monad
It's just standard record syntax. In a type definition such as
data Foo = Foo { a :: Int, b :: String }
it presumably does not surprise you that we automatically get functions a :: Foo -> Int and b :: Foo -> String.
It's absolutely no different for MaybeT. (It does use newtype rather than data but that doesn't matter here, the same would be true if the definition used data instead)
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
this gives us a function runMaybeT :: MaybeT m a -> m (Maybe a) for exactly the same reason that we get the functions a and b in the simpler example above. It's just what record syntax does.
Specifically in this case, as always with a newtype defined using record syntax, the runMaybeT function allows us to "unwrap" a monadic value, going from the abstract MaybeT m a to the more "concrete" representation as a value of type m (Maybe a).
This is used in the implementation of >>= for MaybeT m: since its first argument (x in your snippet) is of type MaybeT m a, we first need runMaybeT to get the "unwrapped" value of type m (Maybe a), then use the >>= of the "base monad" m (shown here with do notation) to "extract" a value of type Maybe a which is then pattern matched on in the usual way.
runMaybeT is a getter. It is a function that takes a MaybeT m a object, and returns an m (Maybe a) object, so it has signature MaybeT m a -> m (Maybe a).
Perhaps it is easier to understand however if we unpack the value with a pattern:
instance Monad m => Monad (MaybeT m) where
return = MaybeT . return . Just
MaybeT rm >>= f = MaybeT $ do
maybe_value <- rm
case maybe_value of
Nothing -> return Nothing
Just value -> runMaybeT $ f value

Unnecessary assignment in do sequence

Let's look at:
instance (Error e) => MonadTrans (ErrorT e) where
lift m = ErrorT $ do
a <- m
return (Right a)
I cannot understand why is necessary a <- m. Why we don't write just:
instance (Error e) => MonadTrans (ErrorT e) where
lift m = ErrorT $ do
return (Right m)
You're reading a <- m as "assign a the value m." That notation for assignment is common in pseudocode, but it means something different in Haskell. You can read it as "Produce a value from m and bind that value to a." To be more precise, in a do block,
a <- m
...
...
is equivalent to
m >>= \a ->
do
...
...
So applying Right to a is sensible, but applying it to m gives you a monadic action wrapped in Either, which isn't usually what you're after.
There is, however, a shorter way to write that instance:
instance Error e => MonadTrans (ErrorT e) where
lift m = ErrorT (Right <$> m)
Nota Bene: ErrorT has generally been supplanted by the more generally-useful ExceptT, which doesn't have the annoying and often-irrelevant Error context. In particular, it's very often useful to have an "exception" value that doesn't actually represent an error and isn't an instance of Show.
m :: m a
Right m :: Either e (m a)
return (Right m) :: m (Either e (m a))
ErrorT $ return (Right m) :: ErrorT e m (m a)
This has the wrong type: we wanted ErrorT e m a.
Instead, when using a <- m, we have:
a :: a
Right a :: Either e a
return (Right a) :: m (Either e a)
ErrorT $ return (Right a) :: ErrorT e m a
which is OK.
(Above some value variables have the same name of type variables on the right of :: -- this is just an incident.)
Alternatives:
instance (Error e) => MonadTrans (ErrorT e) where
lift m = ErrorT $ fmap Right m
or with applicative notation,
instance (Error e) => MonadTrans (ErrorT e) where
lift m = ErrorT $ Right <$> m

Adding state to an Either

I have a function which is something like myFunction below:
data MyError = E1 | E2
f s = if s == "" then Left E1 else Right $ reverse s
g = (fmap reverse) . f
myFunction :: String -> Either MyError (String, String)
myFunction s = do
s1 <- f s
s2 <- g s1
return (s2, s2)
So it calls various other functions which are also in the Either monad, so everything is OK.
Now I have a situation where the type of one of the functions, say g, changes to
g :: CPRG r => r -> String -> (Either MyError String, r)
For reference, the "real-world" code is the decode function here and the function that changes is Jwe.rsaDecode (I'm adding RSA blinding to the decryption function).
As a result, myFunction needs to have the same type, so that I can pass in the CPRG and return it. I'm having trouble seeing how I can carry on using something like the Either monad in combination with passing the RNG, and still be able to extract the final state of the RNG in both the failure and success cases, so that it can be returned.
The type
r -> (Either e a, r)
is a monad transformer. In particular, it's the ExceptT transformer
newtype ExceptT e m a = ExceptT (m (Either e a))
We'll specialize it for State such that
r -> (Either e a, r)
~
ExceptT e (State r) a
So what is a monad transformer? Well, it turns out that often when you take two monads together and stack them you end up with yet another monad. It is not always the case and is a bit tricky to do in general (unlike Applicative where stacks of Applicative functors are always yet again Applicative functors).
That said, the library linked above, mtl, demonstrates a list of common "transformers" which encode common ways of stacking monads. Thus, ExceptT is one of these "recipes" and it is designed such that ExceptT e m a is a monad so long as m is also a Monad.
So now we can create a new type alias
type M r a = ExceptT MyError (State r) a
and write g as a function like
g' :: CPRG r => String -> M r String
g' s = do
r <- lift get -- lift "lifts" State monad computations up
let (e, r') = g r s
lift $ put r'
either throwError return e -- here we generalize an Either
-- into the M monad.

What is this simple function called?

Have you already seen the following function? What is it called? What is it useful for? can it be defined more generically than just for StateT?
simpleFunction (StateT f) = StateT $ (\s -> return (f s, s))
By the way, ghc gives it the type Monad n => StateT s m a -> StateT s n (m (a, s)).
And there is an alternative definition:
simpleFunction m = do
s <- get
mapStateT (\l -> return (l, s)) m
Having two monads like n (m a) isn't usually very useful (the composition might not be a monad etc.). So I guess more usable version would be of type
(Monad m) => StateT s m a -> StateT s m (a, s).
This can be generalized to an arbitrary state transformer over m:
import Control.Monad
import Control.Monad.State
f1 :: (MonadState s (t m), MonadTrans t, Monad m) => StateT s m a -> t m (a, s)
f1 (StateT f) = get >>= lift . f
And since the only thing we need is get, we can further generalize to:
f2 :: (MonadTrans t, Monad m, Monad (t m)) => t m s -> StateT s m a -> t m (a, s)
f2 g (StateT f) = g >>= lift . f
If you really need to have two monads, perhaps MFunctor would be useful - functions like hoist or generalize allow to switch between monads.
The simpleFunction structure is parameterized over two things: a StateT monad and a function f. As it is shown in both given definitions, the simpleFunction gets the state from the internals of the monad, then map both the return value and final state of a computation using a given function.
Following a very simple example to see a working example:
import Control.Monad.State
inc :: State Int Int
inc = do
n <- get
put (n + 1)
return n
simpleFunction = do
s <- get
mapState (\l -> (l,s)) inc
main = do
print $ runState simpleFunction 1
The result is: ((1,2),1) which is the ((return value,final state),initial state)
The simpleFunction as you see is not complicated. It can be used with monads other than StateT. In this case, you have to implement your own map and get.
Hope it's useful!

Why does the following ReaderT String IO lose an IO action?

module Main (main) where
import Control.Monad.Reader
p1 :: String -> IO ()
p1 = putStrLn . ("Apple "++)
p2 :: String -> IO ()
p2 = putStrLn . ("Pear "++)
main :: IO ()
main = do
p1 "x"
p2 "y"
r "z"
r :: String -> IO ()
r = do
p1
p2
It prints:
Apple x
Pear y
Pear z
Why?
The problem is in r. Given the following definition of Reader monad:
instance Monad ((->) e) where
return = const
f >>= g = \x -> g (f x) x
We can simplify r:
r = p1 >> p2
= (>>=) p1 (\_ -> p2)
= (\f g x -> g (f x) x) p1 (\_ -> p2)
= \x -> (\_ -> p2) (p1 x) x
= \x -> p2 x
This also shows that Reader's (>>) is just const with a bit more specific type.
If you want to distribute the environment and then execute both actions, you have to bind the result of applying p1 to the environment, for example:
r = do a1 <- p1
a2 <- p2
return (a1 >> a2)
Or using Applicative:
r = (>>) <$> p1 <*> p2
Expanding on the Reader part, Control.Monad.Reader provides three variants of Reader.
the implicit (->) e, which is what the function r uses
the monad transformer ReaderT e m, a newtype wrapper for functions of type e -> m a
the explicit Reader e, defined in terms of ReaderT as ReaderT e Identity
Without any further information, the implicit (->) e will be used. Why?
The overall type of do block is given by the last expression, which is also constrained to be of the form Monad m => m a for some m and a.
Looking back at r, it's clear that the do block has a type String -> IO () as given by the type of r and also p2. It also requires String -> IO () to be Monad m => m a. Now, unifying these two types:
m = (->) String
a = IO ()
This matches (->) e monad instance by choosing e = String.
Being a monad transformer, ReaderT takes care of the inner plumbing to make sure the actions of the inner monad are properly sequenced and executed. To select ReaderT, it is necessary to explicitly mention it (usually in a type signature, but functions which fix the type to be ReaderT, such as runReaderT, also work):
r :: ReaderT String IO ()
r = do ? p1
? p2
r' :: String -> IO ()
r' = runReaderT r
This comes with another problem, p1 and p2 have a type String -> IO (), which doesn't match the required ReaderT String IO ().
The ad-hoc solution (tailored exactly for this situation), is just to apply
ReaderT :: (e -> m a) -> ReaderT e m a
To obtain something more general, MonadIO type class can lift IO actions into the transformer and MonadReader type class allows accessing the environment. These two type classes work as long as there is IO (or ReaderT respectively) somewhere in the transformer stack.
lift' :: (MonadIO m, MonadReader a m) => (a -> IO b) -> m b
lift' f = do
env <- ask -- get environment
let io = f env -- apply f to get the IO action
liftIO io -- lift IO action into transformer stack
Or more concisely:
lift' f = ask >>= liftIO . f
Regarding your question in comments, you can implement the relevant instances in this way:
newtype ReaderT e m a = ReaderT { runReaderT :: e -> m a }
instance Monad m => Monad (ReaderT e m) where
return = ReaderT . const . return
-- The transformers package defines it as "lift . return".
-- These two definitions are equivalent, though.
m >>= f = ReaderT $ \e -> do
a <- runReaderT m e
runReaderT (f a) e
instance Monad m => MonadReader e (ReaderT e m) where
ask = ReaderT return
local f m = ReaderT $ runReaderT m . f
reader f = ReaderT (return . f)
The actual typeclass can be found in the mtl package (package, type class), the newtype and Monad instance in transformers package (package, type class).
As for making a e -> m a Monad instance, you are out of luck. Monad requires a type constructor of kind * -> *, which means we are attempting to do something like this (in pseudo-code):
instance Monad m => Monad (/\a -> e -> m a) where
-- ...
where /\ stands for type-level lambda. However, the closest thing we can get to a type level lambda is a type synonym (which must be fully applied before we can make type class instances, so no luck here) or a type family (which cannot be used as an argument to type class either). Using something like (->) e . m leads to newtype again.
Let's first rewrite the body of
r :: String -> IO ()
r = do
p1
p2
using (>>),
r = p1 >> p2
so p1 must have type m a for some Monad m, and p2 must have type m b for the same m.
Now,
p1, p2 :: String -> IO ()
and the top-level type constructor in that is the function arrow (->). Therefore the Monad used in r must be
(->) String
The Monad instance for (->) e [aka the reader monad], is
instance Monad ((->) e) where
-- return :: a -> (e -> a)
return = const
-- (>>=) :: (e -> a) -> (a -> (e -> b)) -> (e -> b)
f >>= g = \x -> g (f x) x
and consequently,
p1 >> p2 = p1 >>= \_ -> p2
= \x -> (\_ -> p2) (p1 x) x -- apply (\_ -> p2) to (p1 x)
= \x -> p2 x -- eta-reduce
= p2
so that was just a complicated way to write
r = p2
For r you used (->) String (IO ()) which is a Monad ((->) String) that returns a value of type IO ().
You did NOT use a ReaderT or any monad transformer. You used a monad that returns a different monad. It accidentally compiled and ran, almost doing what you expected.
You need to use runReaderT and lift (or liftIO) to achieve the r that I think you are trying to make.
You left off the argument when you invoke p1 and p2 in r. What you wrote is then interpreted as pointfree notation, so only the second IO action gets an argument. This works:
r :: String -> IO ()
r x = do
p1 x
p2 x
To understand why this is happening, consider that what you originally wrote is equivalent to
r = p1 >> p2
The compiler interprets that as something like
r x = (p1 >> p2) x
Which isn't what you want.

Resources