Search code examples
haskellsyntaxmonadsdo-notation

Is it possible to check some condition before returning from a do block in Haskell?


I'm doing something like this

do
  xs <- xss
  x <- x
  if x > 3
  return x

The line containing the if is giving me a compile error but I'm not really sure about the proper way to write the same thing.

Just to be more clear, in Scala the equivalent of what I'm trying to achieve would be:

for {
  xs <- xss
  x <- xs
  if x > 3
  } yield x

Solution

  • You need to import Control.Monad and use guard

    import Control.Monad (guard)
    
    do
      xs <- xss
      x <- xs
      guard (x > 3)
      return x
    

    Also, as the final if statement in scala is just a filter, you can write it like this:

    do
      xs <- xss
      x <- xs
      _ <- filter (>3) [x]
      return x
    

    Edit, as per comment. Even better:

    do
      xs <- xss
      filter (> 3) xs
    

    While in Scala you are doomed to use yield within a for loop because it's part of a control structure, in Haskell return is just a function and you can avoid using it. In general, as monad rules state, do {someStuff; x <- xs; return x} = do {someStuff; xs}