This is several questions rolled into one:
In do
notation, does each line have to return the same type? For example, can I write one line in a single do
block that returns an IO
monad, and another that returns an integer? (My understanding, based on how the de-sugaring with >>
and >>=
seems to work, is that the answer is no.)
If not, then how does the compiler determine what type the lines must all return? In all the examples I've seen, the author takes it as a foregone conclusion that we're just working with IO
monads. But how do you know, for a given do
block, what each line must return?
Again assuming the answer to #1 is no: How do you use functions that don't return the right kind of monad inside a do
block? For example, consider this websockets code:
application :: MVar ServerState -> WS.Request -> WS.WebSockets WS.Hybi00 ()
application state rq = do
WS.acceptRequest rq
msg <- WS.receiveData :: WS.WebSockets WS.Hybi00 Text
return ()
Suppose I want to print the value of msg
. How would I go about that in a way that doesn't conflict with the type of the do
block?
IO String
and one can return an IO Integer
but they both have to be IO
.let
, remember how in GHCi you must use let to declare local variables, you can do the same in a do
block. let someMonad = doSomething
in
lift
which can "lift" another monad into the transformer. Transformers normally end in a T, eg StateT. Pretty much every monad you use has an equivalent transformer.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With