3 ms·
I'm a bit confused - isn't this how all Static Single Assignment representations in compilers work? And those are used in things like LLVM IR to represent C and
by torginus 2y ago
I'm a bit confused - isn't this how all Static Single Assignment representations in compilers work? And those are used in things like LLVM IR to represent C and C++ code. Is C++ immutable now?
- kqr 2y agoThe difference at the high level is that assigning a variable creates a new scope. E.g. in C I would expect to be able to 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.)
- eru 2y agoBtw, Haskell also supports mutable re-assignment of variables. But it's not something that's built into the language, you get mutable variables via a library. Just like you can get loops in Haskell via a library.
- kqr 2y agoOh, yeah, it's right there in the standard library. But one has to be a little more explicit about the fact that one is accessing truly mutable variables. For example, given the helper utilities checkIORef r p = fmap p (readIORef r) usingIORef r a = readIORef r >>= a the example can be written as main = do i <- newIORef (0 :: Int) whileM_ (checkIORef i (< 5)) $ do modifyIORef i (+1) usingIORef i (printf "i: %d\n") That said, even if one actually needs to mix mutable variables with I/O actions like printing, I'm not sure I would recommend using IORefs for it. But opening the can of MonadIO m => StateT Int m () is for another day.
- deleted 2y ago[deleted]