Live data from Hacker News

Functional Programming Self-Affirmations

norikitech.com

101–110 of 119 posts

Re: Functional Programming Self-Affirmations

#101

Earlier quoted context omitted.

I'm not convinced that you can follow all of these outside of Functional Programming. How can you "Make illegal states unrepresentable" with mutable state and sequences of mutations that cannot be enforced with the type system? How can you do "Errors as values" at a large scale without do-notation / monads? How can you do "Functional core, imperative shell" without the ability to create mini DSLs and interpreters in…

> How can you "Make illegal states unrepresentable" with mutable state and sequences of mutations that cannot be enforced with the type system? I think you're confusing "make illegal states unrepresentable" with "parse, don't verify"? If your type cannot represent any invalid states, there's no way you can reach them through mutation.

The "sequences of mutations" phrasing made me think they were talking about stuff like state machines or handles for external resources—for example calling `databaseConnection.close()` on an already-closed connection, which is usually a runtime error (or maybe a no-op).

Re: Functional Programming Self-Affirmations

#102

I do not work in a functional language, but these ideas have helped me a lot anyway. The only idea here that I find less directly applicable outside purely functional languages is the "Errors as values [instead of exceptions]" one. On the surface, it makes complete sense, the non-locality of exceptions make them hard to reason about for the same reasons that GOTO is hard to reason about, and representing failure mode…

The way Rust solves this is that the type Result is marked with #[must_use] - ignoring it and not deciding what to do with the error raises an warning.

Plus, if you want to bubble the error, you must intentionally use the ? operator, so you are forced to acknowledge the function you called actually may raise an error (as opposed to calling an API you're unfamiliar with and forgetting to check whether it can raise an error, and the compiler not having your back)

Re: Functional Programming Self-Affirmations

#103

Earlier quoted context omitted.

Right, I understand. But my question is, how do you _ensure_ a failure value is dealt with by clients? In purely functional languages, your clients have no choice, they'll have to do something with it. In imperative languages, they can just ignore it.

In Rust, there's a `#[must_use]` attribute that can be applied to types, such as Result, and on functions. This triggers if the return value is not used. It's only a warning though, but you could imagine a hypothetical imperative language making this a hard error

#![deny(must_use)] on the root of your crate makes it a hard error for your whole crate.

Typically what happens is that having this set on is very annoying while developing code, because we often want to test incomplete code without proper error handling before we finish it. So sometimes people will block on this kind of issue in CI, but not error out during development (a warning is more than enough)

Re: Functional Programming Self-Affirmations

#104

I do not work in a functional language, but these ideas have helped me a lot anyway. The only idea here that I find less directly applicable outside purely functional languages is the "Errors as values [instead of exceptions]" one. On the surface, it makes complete sense, the non-locality of exceptions make them hard to reason about for the same reasons that GOTO is hard to reason about, and representing failure mode…

C# nullable reference types with our parameters can kinda resemble forcing you to at least bind variables to the outputs but there’s nothing really like the linear types that we want and deserve

Re: Functional Programming Self-Affirmations

#105

> Make illegal states unrepresentable This is a nice ideal to shoot for, but strict adherence as advocated in the article is a short path to algorithmic explosions and unusable interfaces on real life systems. For example, if you have two options that are mutually incompatible, this principle says you don't make them booleans, but instead a strict enum type populated with only legal combinations of the options. A gre…

True. And what is an "illegal state" anyway? If two options are "mutually incompatible" it means that they, as far as we know, so far, have never occured at the same time. But that is just how things are currently. The world may change. And it's important to strive for maintainable code that can accommodate such change easily. Expanding company operations to work in a different country is an example of this (our) "wo…

So, what, you’d advocate declaring all function parameters and returns as void* to maximize flexibility with respect to future changes in requirements?

Re: Functional Programming Self-Affirmations

#106
post #82

Earlier quoted context omitted.

The difficulty of Making illegal state unrepresentable depends entirely on the domain you're working on. And whether discarding the occasional invalid transaction is viable. If you're writing a CMS/wiki software, it's gonna be pretty straightforward to do. If you're working with transactions, trades, contracts etc, it's not.

>If you're writing a CMS/wiki software, it's gonna be pretty straightforward to do. >If you're working with transactions, trades, contracts etc, it's not. why not? what's the difference between those two categories, mentioned in your last two sentences, as far as this argument about illegal states is concerned? not clear to me. in fact, just a few weeks ago, I saw a video by yaron minsky of jane street about ocaml. t…

> why not? what's the difference between those two categories, mentioned in your last two sentences, as far as this argument about illegal states is concerned? not clear to me.

I kinda began my comment with that reason: The difficulty entirely depends on whether discarding the occasional invalid write is possible. If you can simply return an error and ignore the write/transaction, you're golden.

If you can't, it becomes incredibly complicated

Re: Functional Programming Self-Affirmations

#107
post #82
post #71

Earlier quoted context omitted.

""Make illegal states unrepresentable" is way too expensive to implement." This has not been my experience. The speed increase in development not having to worry about the unrepresentable cases have been very valuable. In addition as requirements change migrating old data hasn't been a huge concern. For code changes refactoring the types helps address new cases as well.

The difficulty of Making illegal state unrepresentable depends entirely on the domain you're working on. And whether discarding the occasional invalid transaction is viable. If you're writing a CMS/wiki software, it's gonna be pretty straightforward to do. If you're working with transactions, trades, contracts etc, it's not.

> If you're working with transactions, trades, contracts etc, it's not.

I don’t mean to rain on your parade here, but there’s quite a few high powered orgs in the finance world that are well known for making extensive use of functional languages.

Jane St is the most famous example but it’s not the only one. Standard Chartered Bank uses a lot of Haskell, as does Barclays and Bank of America.

Re: Functional Programming Self-Affirmations

#108

Earlier quoted context omitted.

True. And what is an "illegal state" anyway? If two options are "mutually incompatible" it means that they, as far as we know, so far, have never occured at the same time. But that is just how things are currently. The world may change. And it's important to strive for maintainable code that can accommodate such change easily. Expanding company operations to work in a different country is an example of this (our) "wo…

So, what, you’d advocate declaring all function parameters and returns as void* to maximize flexibility with respect to future changes in requirements?

No of course not. Just that we shouldn't forget that "specs" can change and typically do. Keep an open mind.. Never say "never". Illegal states can become legal.

Re: Functional Programming Self-Affirmations

#109

Earlier quoted context omitted.

The way to do functional programming in imperative languages is to handle the side-effects as high up in the call-chain as possible. That would mean that you return an instance of Error from lower-level and decide in some higher caller what to do about it. That as an alternative to throwing the error. This way you get the benefit of being able to follow the flow of control from each called function back to each calle…

Right, I understand. But my question is, how do you _ensure_ a failure value is dealt with by clients? In purely functional languages, your clients have no choice, they'll have to do something with it. In imperative languages, they can just ignore it.

Failing to detect a result as error-value is a good failure case to be aware of. But I think if you throw an error it is also possible for a client to fail to handle it properly. No Silver Bullet.

Re: Functional Programming Self-Affirmations

#110
post #106

Earlier quoted context omitted.

>If you're writing a CMS/wiki software, it's gonna be pretty straightforward to do. >If you're working with transactions, trades, contracts etc, it's not. why not? what's the difference between those two categories, mentioned in your last two sentences, as far as this argument about illegal states is concerned? not clear to me. in fact, just a few weeks ago, I saw a video by yaron minsky of jane street about ocaml. t…

> why not? what's the difference between those two categories, mentioned in your last two sentences, as far as this argument about illegal states is concerned? not clear to me. I kinda began my comment with that reason: The difficulty entirely depends on whether discarding the occasional invalid write is possible. If you can simply return an error and ignore the write/transaction, you're golden. If you can't, it beco…

Shouldn't an unrepresentable bad state not even have been proposed as a write tho? I mean the way I understand it, if something is trying to write a bad state somewhere, it is being represented somehow isn't it?
Post reply on HN