Live data from Hacker News

The general value of typed functional programming lies in leaving no edge cases

np.reddit.com

101–110 of 172 posts

Re: The general value of typed functional programming lies in leaving no edge cases

#102

Earlier quoted context omitted.

> the normal mindset of an exception-based programmer is to program for the happy-case and only vaguely think about what happens if it goes wrong. I'm not sure that's such a bad thing. Exception handling doesn't mean you should be handling all exceptions, just that you can recover if one does occur. If an exception is 100% relevant to what you're doing then yes absolutely handle it, or even clean up your own state be…

> Exception handling doesn't mean you should be handling all exceptions, just that you can recover if one does occur. You can't because you don't know where it came from so you don't know what happened, why, or if it was recoverable. You can take a stab at it, but that's it.

> You can't because you don't know where it came from

Maybe that's a particular language constraint? In general exceptions have a stack trace and it's evident where an exception came from.

At least in my experience exceptions don't have to be handled unless or until they're disruptive. If you have a scheduler or task processor code that needs to run continuously then you're going to have robust exception handling, but not necessarily comprehensive or appropriate. For other areas of code however the exception handling isn't necessarily requisite.

Re: The general value of typed functional programming lies in leaving no edge cases

#103
post #60
post #57

For me the value of typed functional programming has been it's ability to encode business logic in to the type system and thus validate some of my logic at compile time.

What's specifically functional about this advantage. Can't you encode the buisness logic into types in non-functional languages as well?

You can encode it, but it is not enforced. For instance, I can refer to every instance/argument when I use a Person object as `person` or whatever name of the class is, but when you have many developers working on a large system, these things tend to slowly spiral unless you establish strict guidelines early on and enforce through code reviews.

Or you can use types where it's enforced by the compiler.

Re: The general value of typed functional programming lies in leaving no edge cases

#104
post #63
post #44

I am not sure this is the only value, but it is generally true. And this is one of the great advantages of haskell. By the way, now that I know some haskell, I see this edge case sloppiness all the time and it is really annoying. For example, here is something that annoyed me just recently. You go to yahoo finance and there they will show you the revenues of a company as well as the revenue growth from past year. But…

Ive noticed other languages with this feature, they call them optional types, you can pass in a null or a type value. /s slightly, maybe more snarky, but seriously, optional types are way overhyped. Null objects are far more useful than optionals. Optionals tend to leak all over the show.

I upvoted you because I think it's unfair that you are being downvoted while contributing to the discussion, that said you are completely wrong. Without Optional/Maybe nulls leak everywhere except you have no idea where they are. This leads programmers to engage in defensive programming for all references since there is nothing to help them understand what they should expect to be null in some cases. Optional/Maybe encourages good data modelling by making values that might be missing very clear. It encourages a style of programming that eliminates these issue via better modelling or by rejecting bad data earlier.

For example consider a network response that in a JS app might be passed around as an opaque object. In a language like Swift this is infeasible, you have to transition from the network serialized version to concrete models at the network layer. If you encounter mismatches in the expectation of what is optional you have to handle it here at the edge of the program. This enables massively safer code and makes reasoning about your program much simpler if anything.

As a concerete example say an API response tells you if a user is verified(for some domain specific definition of "verified"), additionally you want to know when they were verified maybe to give them a hint when they need to do it again. You coudl model this as:

    {
      "verified": false,
      "verified_at": null
    }
before they have verified and

    {
      "verified": true,
      "verified_at": "2020-02-24T15:31:12Z"
    }
after they have verified.

In Swift this would then be modelled as

    struct Users {
        let verified: Bool
        let verifiedAt: Date?
    }
However this introduces an Optional which complicates code that needs to deal with users who are verified or not. Instead you could model the same thing and avoid this issue as:

    {
      "verification_status": {
        "status": "unverified"
      }
    }
for the unverified case and

    {
      "verification_status": {
        "status": "verified",
        "at": "2020-02-24T15:31:12Z"
      }
    }
for the verified case. In Swift this can be nicely modelled without any Optionals using an enum

    enum VerificationStatus {
        case unverified
        case verified(Date)
    }

    struct User {
        let verificationStatus: VerificationStatus
    }
Better optional value visibility leads to better data modelling.

Re: The general value of typed functional programming lies in leaving no edge cases

#105
post #78

Earlier quoted context omitted.

Any language with a type system at all can create a Maybe type. The difference is that failing to handle the None case is a runtime exception in most languages where in Haskel/Rust it won’t compile. I don’t know of any mainstream language that has bolted on that level of verification.

Scala3 and Kotlin.

You mean Scala 2. And likely even Scala 1 had this. (Scala 3 is still in development).

But Kotlin? Since when does Kotlin have pattern matching with exhaustive checks? Also it does not have an `Maybe a` / `Option[A]` type out-of-the box.

Re: The general value of typed functional programming lies in leaving no edge cases

#106
post #46
post #28

Earlier quoted context omitted.

This is also one of the problems with programming with exceptions. You lean on the fact that an exception will be thrown and just propogate up until it finds something, so the normal mindset of an exception-based programmer is to program for the happy-case and only vaguely think about what happens if it goes wrong. I know, I've written a lot of code in this style for many years myself. In some cases, that's not a pro…

There's also the OTP model, where you have exceptions as well as a robust "something" up there. You don't have to deal with the minutiae, and the pattern (processes (aka, isolated processes) and restarts) lets you deal with known or unknown errors.

Right, but the OTP doesn't make you deal with the exceptions upfront, only to architect your app in the way that they don't crash or infect other parts of the system.

Re: The general value of typed functional programming lies in leaving no edge cases

#107
post #35
post #29

Earlier quoted context omitted.

This isn't particular of Rust. Nim also forces you to deal with all possible branches of a case statement. I'm pretty sure other languages do so as well. This is just basic type safety stuff.

plenty of other languages do so, but it's both unfairly diminishing to the parent & questionably correct to refer to it as "basic type safety stuff"

On the other hand, it's not a very advanced type level feature either to insist on total functions. I'm sure Rust's type system goes a lot further in enforcing a good level of type soundness.

Edit: typo

Re: The general value of typed functional programming lies in leaving no edge cases

#108
post #63

Earlier quoted context omitted.

Ive noticed other languages with this feature, they call them optional types, you can pass in a null or a type value. /s slightly, maybe more snarky, but seriously, optional types are way overhyped. Null objects are far more useful than optionals. Optionals tend to leak all over the show.

Nulls leak exactly as badly as optionals, except it's additionally impossible to tell where nulls have leaked to.

Actually, nulls leak worse than optionals, because it's impossible to tell where nulls have leaked to (so you end up forgetting to filter out a null at a interface where you would have decided to filter out a maybe).

Re: The general value of typed functional programming lies in leaving no edge cases

#109
post #91

Earlier quoted context omitted.

You're right, it does, and it exists at the value level if you are using floating point. But in Haskell you have, for example, Rational numbers to avoid many such problems. I was, however, surprised to not see any kind of a (significant) `safeDiv` function on hackage, and no NonZero newtype (outside of quickcheck). But, for this kind of thing its so easy to roll yourself, I am guessing this is what people do (and I h…

> But in Haskell you have, for example, Rational numbers to avoid many such problems. Hey, it's for sure nice to have a rich numeric stack (see also some lisps), but in numeric work "use something else" is very rarely a practical answer to issues with IEEE-754.

Sure, it is, but the thing is that a hugely significant amount of the time I've seen those NaNs happen is because of a lack of understanding/care on the part of the devs, and not because they are doing scientific computing.

There seem to be a large disconnect here. A big chunk of people don't need the speed that FP math brings, what they need is exactness. And, for most languages with a C-based lineage, actually correct floating point math support seems to fit in the "someday/maybe" categories.

Re: The general value of typed functional programming lies in leaving no edge cases

#110

Earlier quoted context omitted.

Scala3 and Kotlin.

You mean Scala 2. And likely even Scala 1 had this. (Scala 3 is still in development). But Kotlin? Since when does Kotlin have pattern matching with exhaustive checks? Also it does not have an `Maybe a` / `Option[A]` type out-of-the box.

Kotlin distinguishes between nullable and not-null references, which is an alternative to the maybe type. It serves roughly the same purpose, to replace runtime errors with compile-time verification that you haven't missed a corner case.
Post reply on HN