Is do notation used necessarily in the context of monad?

蓝咒 提交于 2019-12-02 08:20:45

问题


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)}

回答1:


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:

  1. do {foobar; ...} = foobar >> do {...} (aka foobar >>= \_ -> do {...})
  2. do {a <- foobar; ...} = foobar >>= \a -> do {...}
  3. 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.




回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!