Reputation: 375
We know that the do block is just syntactic sugar. But then how does it figure out which monadic context it is in? Assume we don't use <-
operator anywhere in the do block.
Upvotes: 3
Views: 1588
Reputation: 62848
Maybe some "practical" examples will help:
foo1 = do
print 5
return 7
-- print belongs to the IO monad. This whole thing is in IO.
foo2 x = do
writeTVar x 7
return 11
-- writeTVar belongs to the STM monad. This whole thing is in STM.
foo3 = do
let x = 5
[1, 2, 3, 4]
-- Last line is a list expression. This whole thing is in the list monad.
foo4 = do
put 7
return 9
-- put is in the State monad. This whole thing is in the state monad.
foo5 = do
x <- magic1
y <- magic2
return (x, y)
-- This is in whatever monad magic1 and magic2 are in.
foo6 = do
return 13
-- Doesn't mention any monad. Works for ALL POSSIBLE MONADS!
foo7 abc def = do
x <- abc
y <- def
return (x, y)
-- Runs in whatever monad abc and def run in.
-- By passing different arguments, you can CHANGE which monad that is!
Upvotes: 7
Reputation: 53901
It uses the same general type class mechanism that is used to figure out which +
to use or even what numeric type to use for literals. That is,
something like
do
return True
Will not divine the specific monad that it should use but rather just be assigned the type Monad m => m Bool
. This constraint says that the do-block has the type m Bool
for any m
which happens to have implemented the Monad
type class. Moreover, whenever this block is used, the specific instance will be inferred from the context of its use.
If we use operators that are tied to a specific Monad
, this will force the type to become more specific. For instance, if we use modify :: (a -> a) -> State s a -> State s ()
(I'm simplifying the type for the sake of example here) then this will force the block to have the type State s ...
. In general, Haskell will figure out the most general type possible and make use of type class constraints to make sure that the types in question implement the appropriate operations.
Upvotes: 10