Saki
Saki

Reputation: 85

Can I use let in guards on Haskell?

right now I have an error that says parse error on input ‘|’ that refers to the '|' before the if statement. I am also not sure if I can use let in guards like the code below. The code below is an example to my problem, please help to correct my mistakes, thank you in advance!

func x y
   | let 
       sum = x + y
       mult = x * y
   | if sum == 3
       then do
            sum+=1
       else if mult == 5
           then do
                mult -=1

Upvotes: 4

Views: 6490

Answers (3)

Z-Y.L
Z-Y.L

Reputation: 1779

In fact, Haskell2010 allows the let expression to appear in the guard. See the report here. |let decls introduces the names defined in decls to the environment.

For your case, we can write

fun x y 
  | let sum = x + y, sum == 3 = Just (sum + 1)
  | let mult = x * y, mult == 5 = Just (mult - 1)
  | otherwise = Nothing

Upvotes: 5

Redu
Redu

Reputation: 26161

You can use let in the top however it has to be followed by an in to designate the block where the defined values are to be used. Also you are missing the condition about what to do if sum /= 3 and mul /= 5. So may be returning a Maybe type could be better such as

func :: Integral a => a -> a -> Maybe a
func x y = let sum = x + y
               mul = x * y
            in case (sum, mul) of
               (3, _) -> Just (sum + 1)
               (_, 5) -> Just (mul - 1)
               _      -> Nothing

Upvotes: 2

chi
chi

Reputation: 116139

Unfortunately, we can not do that with let.

More precisely, we can write

func x y | let z = .. in condition = result
         | otherCondition          = otherResult

but z will only be visible in condition, and not in result, otherCondition or otherResult.

(This can be improved using pattern guards, but not completely: z will still be unavailable in otherCondition and otherResult)

The solution is using where instead:

  func x y | condition      = result
           | otherCondition = otherResult
           where z = ...

Here, z is visible everywhere.

(Personally, I dislike this form of where because it is too far from the uses of z, but I can't see any simple alternative in this case.)

Finally, let me add that your code does not look functional to me: there's no if then without else in functional programming, and mult -= 1 can not modify variable mult (the same holds for sum += 1).

Upvotes: 3

Related Questions