haskellfunctional-programmingmonadsequivalencedo-notation

Haskell: Understanding do notation with if-else statements


I have the following code for an API for manipulating a robot:

data Direction = Left | Right
forward    :: IO ()
blocked :: IO Bool
turn       :: Direction -> IO ()

I am trying to understand two programs that will move the robot forward unless it is blocked by an obstacle, in which case, the robot should turn in the Right direction.

However, I am not sure what is the difference is between the following two programs:

-- program 1
robot = do
  detected <- blocked
  if detected 
    then turn Right
    else forward
  robot

-- program 2
robot = do
  detected <- blocked
  if detected
    then turn Right
         robot
    else forward
         robot

The line detected <- blocked takes the boolean value out of the IO. If the condition if detected evaluates as true, then the robot turns Right, otherwise the robot moves forward. In program 1 the function robot is called again after moving the robot either right or forward. In program 2, the function robot is called directly after turning right or moving forward.

I am not sure what the difference is between calling robot after the if-else statements (in program 1) versus calling it in the then and else case in program 2. Am I correct in saying that these two programs are equivalent? Any insights are appreciated.


Solution

  • You are correct in saying that these two programs are equivalent. More generally, if cond then (x >> action) else (y >> action) is equivalent to (if cond then x else y) >> action. This is a consequence of the fact that f (if cond then x else y) = if cond then (f x) else (f y); if you take f = (>> action) you get the equivalence for monads.