2

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
heapOverflow
  • 1,195
  • 2
  • 15
  • 28
  • 2
    replace `if` with `guard` – Jason Hu Feb 25 '18 at 22:08
  • https://hackage.haskell.org/package/base-4.10.1.0/docs/Control-Monad.html#v:guard – Jason Hu Feb 25 '18 at 22:09
  • @HuStmpHrrr: `Variable not in scope: guard :: Int -> Int` . Maybe I'm doing something wrong? – heapOverflow Feb 25 '18 at 22:10
  • also you might find this helpful: https://wiki.haskell.org/Do_notation_considered_harmful – Jason Hu Feb 25 '18 at 22:11
  • 3
    @HuStmpHrrr if you want to answer a question, _answer_ it, don't comment, but be sure to actually know the answer. I'm not sure `guard` actually solves the problem here, and anyways any suggestion for `guard` should explain how one can imitate/implement it oneself using `if`. Also, `guard` does not require any package, only a _module_ import (`Control.Monad`). – leftaroundabout Feb 25 '18 at 22:18
  • 5
    @heapOverflow could you briefly explain what exactly that Scala code does, or give a simple concrete example? – leftaroundabout Feb 25 '18 at 22:19
  • @sorry about the miswording. however, why do you think guard does not solve the issue? – Jason Hu Feb 25 '18 at 22:28
  • @leftaroundabout It's the same as `[x | xs <- xss, x <- xs, x > 3]` – amalloy Feb 25 '18 at 22:34
  • @HuStmpHrrr Well in this case it is extremely unclear what the problem is. The OP even posted showing it doesn't solve the problem because there isn't even a monad in use... that or they forgot to use paren such as `guard (x > 3)`. – Thomas M. DuBuisson Feb 25 '18 at 23:39
  • 3
    What should the result be if x is not > 3? And FYI there isn't really a concept of "before returning" in Haskell. `return` means something entirely different to what you think coming from other languages. – user253751 Feb 26 '18 at 04:57
  • 1
    I agree that naming the function `return` was probably a bad idea (not because of the name itself, but because imperative languages use it for a totally different semantical concept), but `return` actually does not *terminate* the control flow (per se), nor does it mean that it per se returns a value. – Willem Van Onsem Feb 26 '18 at 08:18

1 Answers1

4

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}

Euge
  • 699
  • 10
  • 14
  • 1
    Or even even betterer: `do {xs <- xss; filter (> 3) xs}`. It's always unnecessary to write `x <- foo; return x` instead of just `foo`. – amalloy Feb 26 '18 at 04:07