Hacker News new | ask | show | jobs
by cmrdsprklpny 2071 days ago
My understanding (which there's a good chance is incorrect) is that all code written in Elm has to be in a functional style because the language strictly enforces it; but this enforcement doesn't exist in Lisp and OCaml, so they can be used to write imperative or object-oriented code, as happened in the cases described.
1 comments

Haskell enforces purity, but you can still write pretty imperative looking code by using monads (e.g. some state monad). I don't think there is any philosophical difference between say

  int x = foo();
  bar();
  char y = baz(x);
and

  do
    x <- foo
    bar
    y <- baz x
I'd say the true difference is more related to how you describe state change. Imperative is about having a sequential list of instructions that all can mutate global state in some way, whereas with a functional style it's about composing functions that depend on their arguments rather than global state. Functional purity lends itself to a functional style, but you can just explicitly pass a large (global) state around and compose functions only sequentially, which imo lands you right back in imperative territory.
I'd say there is quite an important conceptual difference in that the state monad example exactly desugars to pure functional code. Monads give us a good syntax for sequential computation, but this sequentiality is built out of purely functional components.
The State monad desugars to pure code, but the IO monad doesn't. If you use IORefs or MVars, then you do actual, real mutability by changing the value at a location.
How would you handle state other than passing it around?

The fundamental thing that Haskell and Elm do is that they don't have mutable values. They create a new value from the old one. You never mutate a record the way you mutate a JS object or a Python dict.

> How would you handle state other than passing it around?

By only passing and updating the relevant bits of state.

>The fundamental thing that Haskell and Elm do is that they don't have mutable values. They create a new value from the old one.

If we're talking about the context of a game, you'll be very likely using monads where this isn't the case (IO, ST). Not to mention, even if you do just use a normal state monad, if you don't keep the old value around, there's no functional difference between mutating the entire program state and creating a new program state while forgetting the old.