简体   繁体   中英

Haskell list monad and return ()

Consider the following piece of code:

foo :: [Int]
foo = do
  x <- [1..10]
  if x < 5 then pure () else [] -- Control.Monad.guard (x < 5)
  pure x

foo2 :: [Int]
foo2 = 
  [1..10] >>= \x ->
    if x < 5 then pure x else [] >>= \y ->
      pure y

In foo , I have manually inlined Control.Monad.guard (x < 5) , as noted in the comment.

Why does foo compile, even though there is pure () in the code? How does the [()] pass the type check? Is it a special case for the do syntax? If yes, is it described anywhere?

In foo2 , I attempted to "desugar" foo without the do syntax. Note that there can't be any pure () , as it doesn't pass type checking.

I'm using ghc-8.8.4 if that's important.

You have several errors in your manual desugaring. One attempt that uses only >>= would be:

foo2 :: [Int]
foo2 =
  [1..10] >>= \x ->
    (if x < 5 then pure () else []) >>= \_ ->
      pure x

First, the parentheses are important: you're binding the result of the entire if expression, not performing a bind inside of its else branch. Second, you can't just introduce a new variable y and then use it in your pure result. Desugaring preserves the same expressions in your source code, it just moves them around a bit. So, pure x must desugar to pure x .

Hopefully you can see why this works: the type of () does not matter, because nobody ever looks at its value, and the result, pure x , has the right type regardless.

But really GHC doesn't produce quite this code: x >>= \\_ -> y is equivalent to x >> y , and that's what's used for a statement in a do-block that does not bind its result to a variable. So really you get

foo2 :: [Int]
foo2 =
  [1..10] >>= \x ->
    (if x < 5 then pure () else []) >> pure x

And you can, if you prefer, use a slightly fancier operator from Functor to achieve the same result. Let's un-inline guard , and use (<$) :: Functor f => a -> fb -> fa instead of a monadic operation. x <$ y is the same as y >> pure x :

foo2 :: [Int]
foo2 =
  [1..10] >>= \x ->
    x <$ guard (x < 5)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM