int i = 0;
while (i < 5) {
i = i+1;
printf("i: %d\n", i);
}
whereas in Haskell I could hypothetically something like let i = 0 in
whileM (pure (i < 5)) $
let i = i + 1 in
printf "i: %d\n" i
but the inner assignment would not have any effect on the variable referenced by the condition in the while loop – it would only affect what's inside the block it opens.(And as GP points out, i=i+1 is an infinite loop in Haskell. But even if it was used to build a lazy structure, it would just keep running the same iteration over and over because when the block is entered, i still has the value that was set outside.)