Haskell report 2010 says
A do expression provides a more conventional syntax for monadic programming. It allows an expression such as
putStr "x: " >> getLine >>= \l -> return (words l)
to be written in a more traditional way as:
do putStr "x: " l <- getLine return (words l)
Haskell the Craft of Functional programming by Thompson says
We'll continue to use the do notation, but will keep in mind that it essentially boils down to the existence of a function (>>=) which does the work of sequencing I/O programs, and binding their results for future use.
Do the above mean that do notation is used necessarily in the context of monad?
If yes, why does the following functor use the do notation?
instance Functor IO where
-- fmap :: (a -> b) -> IO a -> IO b
fmap g mx = do {x <- mx; return (g x)}
Yes. As the article quoted states, do
-notation is simply syntactic sugar for the monad operations.
These are the rules for de-sugaring do
-notation:
do {foobar; ...} = foobar >> do {...}
(akafoobar >>= \_ -> do {...}
)do {a <- foobar; ...} = foobar >>= \a -> do {...}
do {foobar} = foobar
Necessarily this means that do
-notation works entirely on monads, except in the trivial case that rule 3 describes.
So for instance, as the article states, do {putStr "x: "; l <- getLine; return (words l)}
is exactly equal to putStr "x: " >> (getLine >>= \l -> return (words l))
, which you may confirm via the de-sugaring rules.
In the definition for Functor IO
you quote above, the Monad IO
instance has already been defined, and so we are using it to define the Functor
instance, too.
It may also be useful to note that all monads are necessarily functors (see the definition of the Monad
typeclass), so when one says do
-notation works on monads, it also necessarily works on the functors as well. I suspect this may be a point of confusion.
It is worth noting that in certain restricted cases, it is possible to use only Applicative
operations rather than the more general Monad
operations. For instance, the example the article provides could be written as putStr "x: " *> (pure words <*> getLine)
. There is an experimental language extension called ApplicativeDo
which adds to GHC the capability to recognise these situations and generalise certain cases of do
-notation to all applicatives, not just all monads.
Well, with RebindableSyntax extension it will use whatever (>>=)
, (>>)
, and fail
are in scope. So technically Monad
is not required in such case and you can do something as silly as:
{-# LANGUAGE RebindableSyntax #-}
a >>= b = b a
return a = a
-- test == ("foo","boo")
test = do
a <- "foo"
b <- "boo"
return (a,b)
来源:https://stackoverflow.com/questions/57192516/is-do-notation-used-necessarily-in-the-context-of-monad