| I personally haven't had the same experience as you (I personally find the Haskell community quite pleasant, especially in the functional-programming slack server), but I'll try and answer (probably in an incomplete way) your question about updates. Haskell can, in fact, update variables. Mostly through 2 mechanisms: - ST (a computation containing local, mutable state, that cannot escape its scope) [1] - IORef (mutable, thread-safe variables that only work in IO). [2] The other (and usually more common way) of doing "mutable" state in Haskell is through State, which technically doesn't update the variable in-place, but simply modifies the variable and passes a copy to the rest of the computation (although, as far as I'm aware, a lot of the time this step gets optimized away). That said, if your main field of expertise is simulation programs where performance and space efficiency are very important, then Haskell is probably not a great fit (cause not only is it based on a GC, it's also lazy, which can sometimes mess with the performance of your code, not speed-wise but memory usage-wise). Hopefully this could be mitigated in some way in the coming years when Linear types become viable for efficient resource usage (Linear types ideally could grant us some sort of Rust-like resource management) [1] https://hackage.haskell.org/package/base-4.14.0.0/docs/Contr... [2] https://hackage.haskell.org/package/base-4.14.0.0/docs/Data-... |
The very immutability of Haskell values means one has to use transactional logic - given current situation, compute situation at next step. C++ and many other languages tend to update values in-place and that brought me a lot of bugs to debug and, subsequently, made me use Haskell.
Laziness plays a critical role in free composition of parts of the system.
Let me present you some examples.
Single clock domain computing hardware can be thought as computations that compute values for every raising edge of a clock. It can be described as a function from infinite list of inputs to infinite list of outputs. The adder, for example, is just like this:
The register is a thing that produces values remembered from the previous clock cycle. The very first value comes from reset: Mealy machine allows you to apply a function that transforms input and internal state into output and next internal state. Mealy machine can be used for description of all kinds of things, from register files upwards. That's it!Using regular map and other list functions and these two additions, one can simulate single clock domain hardware which amounts to almost anything that computes on silicon - within bounds of approximation; basically, one need to add delays for slower hardware somehow.
The trick with shortcircuiting above allows one to freely compose hardware simulation from different parts. You just put blocks there and they start to work. The function in Mealy machine is pure and total and can be tested (or verified) thoroughly in standard simple way.