Remix.run Logo
bunderbunder 2 days ago

Maybe not in literally every language, but, to cherry pick some examples:

Java (along with many other object-oriented languages) lets you create objects that are effectively immutable by declaring all fields private and not providing any property setters or other methods that would mutate the state.

Errors as values is one of the headline features of both Go and Rust, neither of which has do notation and monads.

Functional core, imperative shell is something I first learned in C#, but I don't think it was _really_ at significantly more of a disadvantage than most other languages. The only ones that let you really enforce "functional core, imperative shell" with strong language support are the pure functional languages. But people working in, say, Ocaml or Scala somehow still survive. And they do it using the same technique that people working in Java would: code review and discipline.

None of this is to say that language-level support to make it easier to stick to these principles is not valuable. But treating it as if it were a lost cause when you don't have those features in the language is the epitome of making the perfect the enemy of the good.

neonsunset 2 days ago | parent | next [-]

Coincidentally, "functional core, imperative shell" is how most companies get to adopt F# from what I was told (and had seen). It integrates really well. C# itself is a proper multi-paradigm language nowadays, and so is also quite successful at employing functional constructs.

timClicks 2 days ago | parent | prev [-]

I consider Rust's Result<T, E> and Option<T> to be monads. Is this incorrect?

bunderbunder 2 days ago | parent [-]

Depending on what functions are in there, they are. But you can make types that happen to be monads in C, too. All you need is a datatype with `return` and `bind` functions that follow a certain spec.

What makes Haskell different is that it has a language-level concept of a monad that's supported by special syntax for manipulating them. (C# does, too, for what it's worth.) Without something like that, observing that a certain type can be used as a monad is maybe more of a fun fact than anything else.

(ETA: for example, many, many languages have list types that happen to be monads. But this knowledge probably won't change anything about how you use them.)