Live data from Hacker News

Fear, trust and JavaScript: When types and functional programming fail

reaktor.com

101–110 of 210 posts

Re: Fear, trust and JavaScript: When types and functional programming fail

#101
post #10

But in JavaScript, the fear is always with you. That's why we have both tests and code reviews. Aside from that I'm surprised the author didn't mention checking constructors. It's arguably the most dependable way of checking if something is of a certain type. But I agree that it's a shame that TS/Flow lose their ability to check types whenever partial application or currying is involved - it's not like it's impossibl…

I did Objective-C work for a decade under such conditions. It's never enough to have tests and code reviews. Static typing is strictly better.

This sounds like an if-it-compiles-it-works argument.

Re: Fear, trust and JavaScript: When types and functional programming fail

#102
This article is bizarre. Firstly, the author states the problem that data can propagate and suffer loss/mutation over time. He then cites types (which absolutely do solve this problem), but then dismisses them saying:

> Adding types to our example doesn’t solve the underlying problem. It improves trust within the code base by helping to ensure that data is used consistently, but it says nothing about data received from the outside world.

But anyone who's used type-based programming knows this is nonsense if you simply write a typed parser (of particular interest to gradually-typed Javascript is packrat-style parsers). Then, your code needs to specify what it wants and what its policy is if it doesn't get it.

But if the author was imagining that compile time integrity and correctness checks could EVER perform runtime checks... well... they're not even wrong they're misunderstanding the function so badly.

The author then proposes out of left-field:

> But it’s like plugging holes in a leaky ship. The problem isn’t just that you can’t trust the types in your system, but that you think you can. You rely on the types to tell you when a change breaks something, but because they were quietly disabled by an any type, or by use of a library, or by a soundness issue, it doesn’t. Types in JavaScript are different from types in most other languages people use: They can’t be trusted in the same way.

Which is both true and useless. Yes, it's true that type circumvention methods exist, and you never really can know if you're calling into a library that circumvents your type constraints unless you read the code. But yes, that's useless because nearly every typed language also has this mis/feature, including OCaml, Haskell, C++17 and even Rust! So the author is not actually giving a real recommendation or even novel insight.

And then we get the final substantive giving us arguments that the author has themselves just discredited:

> Or you change the game and just use PureScript. Or ReasonML, or Elm, or even ClojureScript. These exist today. Production software runs on them. They work with the JavaScript ecosystem, where necessary. And they provide a higher base level of trust in the code that you write and an environment where immutability, functional programming, and types (where applicable) work well and work together.

Firstly, I've written a fair amount of Purescrpt and we call into unsafe code ALL THE TIME for the sake of expediency in Purescript. To even pretend otherwise is just... either it's willful lying or someone who has barely interacted with the Purescript ecosystem in any production fashion.

If you use a dependency and don't vet it somewhat (or at least trust a crowd to vet it as a minimal effort) then you're in for a bad time. Pretending otherwise, or that this is a unique flaw of Javascript, is just wrong.

And if you disagree with that, then I have a challenge for you. I propose to you that you can substitute ANY language and runtime's type and GC as "types" and "assembly" as underlying javascript and not change any underlying axiom presented in this article.

Re: Fear, trust and JavaScript: When types and functional programming fail

#103

Static types are great because they make certain classes of bug impossible to write, but they have their limits. There are escape hatches, like casts and Object types, even in statically-typed languages, though fewer of them in languages with more advanced type systems. There are reasons to like PureScript over TypeScript, just as there are reasons to like Haskell over Java. TypeScript doesn’t give you a way to ban s…

All good points, but I'm having a hard time with this statement:

"There is still value in a function declaring that its argument is of type User (and not defensively checking it) even if it is theoretically possible, in the presence of a bug, though unlikely, that the argument is not really a User."

I'm trying to think of a statically-typed language that would allow such a thing, and I can't, so I assume that you're referring to TypeScript here where you have a world where things are "partially-typed" ?

Re: Fear, trust and JavaScript: When types and functional programming fail

#104
post #91

This article is just a recapitulation of the old pure functional programming vs. imperative programming argument but wrapped up in new packaging. Most of these issues, such as needing to validate types at codebase boundaries, functions that have side effects, and unsound static type systems, could just as easily be leveled at most imperative languages (C++, Java). So yeah, go use a proper functional language (many of…

[deleted]

Re: Fear, trust and JavaScript: When types and functional programming fail

#105
post #100

Earlier quoted context omitted.

You would never be able to write the infinite amount of tests necessary to supplant static typing, let alone run them.

Well don't lose sight of the goal. The goal is less bugs. Static typing is just for internal quality. Users don't give a rat's ass if your types are correct as long as the program works. Proof: Many wildly and massively successful programs are duck-typed. Nobody ever cared to use tests to replicate what a type system does. That's a straw man. Tests go straight for the actual goal by testing actual values. Correct val…

"Static typing is just for internal quality."

Frankly, I don't even know what to do with such a statement. What is your definition of "internal" ?

I just did a very large re-factor of a codebase a few days ago where I changed a lot of event handler (method) types in a codebase of around 200K lines of code (Object Pascal). This means that the method signature of every single event handler could have been wrong in some way if I made a mistake, and it would have introduced a pretty egregious, non-internal bug in every case. How would you test such a massive change without replicating every single thing that a static type system and compiler already do for you ?

Re: Fear, trust and JavaScript: When types and functional programming fail

#106

> in various cases the types are wrong and the compiler doesn’t care It's disturbing how often I encounter this in TypeScript. Or its inverse: the types are correct and the compiler is wrong. Or a third common problem: the types for a library are incorrect. The unsoundness of TypeScript is not merely theoretical. The compiler is frequently just wrong. For that reason, I am mystified by the amount of enthusiasm for Ty…

In what cases have you seen the compiler refuse to accept something that’s correct?

Re: Fear, trust and JavaScript: When types and functional programming fail

#107
But you still have to validate and parse unstructured data in Haskell as well. And what would be the point of having the type checking done at run time? That's what many dynamic programming languages already do. If you're curious about Flow or TS then you must already have a problem with that approach.

Type checkers are tools that help us reason about, structure, and correct code. That's all.

Flow is decent these days but will probably never be as powerful as Haskell. My only gripe is that it forces my team to write verbose code at times in order to gain the benefits: you lose point-free style, gain a bunch of identity and instance checks... but it's a small trade off to make.

One small trick worth remembering and using in Flow to gain something similar to exhaustive type checking is to cast to the empty type in the default case when pattern matching on a type[0].

It's not an elegant type system but if you have experienced a good type system (like Haskell's) then it does make using Flow/TS much easier.

[0] https://medium.com/@ibosz/advance-flow-type-1-exhaustive-che...

Re: Fear, trust and JavaScript: When types and functional programming fail

#108
post #98

Earlier quoted context omitted.

Same here. I have been using Flow (mostly) and TS (occasionally, including counter-checking problems in Flow to see what TS does in a similar case). Overall I would not go back to the time without a type checker, however, I too am mystified by the enthusiasm. Anyone who wants to check the state of static type checking for Javascript should take some time and read through - https://github.com/Microsoft/TypeScript/issu…

> I spent more time working on the types than on the actual code. That's interesting. I very strongly don't, when writing TypeScript (but I don't then also mess around with a second type system on top of it). Better Intellisense and fail-up-front checking means I write code much, much faster. I didn't have to change my coding style because this is already how I wrote code; I now have the tools to actually do it well.…

How much time you spend depends on your data structures. If the easy default options are good enough you don't need to sweat. We make heavy use of disjoint unions, and while the simple case here too is easy, some things that we do - although they still are very simple on the Javascript side - are hard on the type checker (Flow in this case).

> TypeScript is not a "complex dynamic" language

I don't know what you read into my comment, but if you just stick to what I wrote, Javascript certainly is, and TypeScript is just Javascript (the type annotations are a separate thing). I'm not sure what your point is overall I have to admit, it's a bit on the defensive side for no reason that I can see. For whatever reason you seem to feel personally attacked ("I didn't have to change my coding style")? I refer back to what I wrote, point for point. Would it please be allowed to write down my observations? Especially when it is base don years of practice in all the relevant technologies (JS, TS, Flow) and I'm not just making stuff up without having data (i.e. actual experience). Plenty of other people wrote similar comments here.

Re: Fear, trust and JavaScript: When types and functional programming fail

#109
post #92
post #90

Earlier quoted context omitted.

You’ve clearly had a blessed and gentle career

I've worked for very large companies whose massive codebases are littered with defensive checks that have piled up over many years. Invariably, I find that this is because, when the initial wave of defensive checks inevitably broke down because they guard against something that itself changes behavior again, more defensive checks were added. All of this could have been avoided if those companies had just created a cu…

>had just created a culture, from the beginning...

Were it such an easy thing...

Here's how I've experienced such things:

I write naive code. Application hard fails. Test environment down - everyone cross with me.

Me: Yo upstream - fix your data please.

...no response.

So I raise a ticket to get data source fixed - send it to the backlog.

Me: Yo delivery - can we get this ticket prioritised, assigned and put into a sprint?

Delivery: Yeah... nah - cause y'know... delivery.

Me: Yo leadership - can we get a decision taken on whether or not upstream should fix their data, or whether we should just program defensively? If the former - can someone tell delivery to tell upstream?

...no response.

At this point - I give up. Write my little defensive check and admonish myself to do so consistently from now on. Commit, push... go home - sleep like babe.

Re: Fear, trust and JavaScript: When types and functional programming fail

#110
post #98

Earlier quoted context omitted.

> I spent more time working on the types than on the actual code. That's interesting. I very strongly don't, when writing TypeScript (but I don't then also mess around with a second type system on top of it). Better Intellisense and fail-up-front checking means I write code much, much faster. I didn't have to change my coding style because this is already how I wrote code; I now have the tools to actually do it well.…

How much time you spend depends on your data structures. If the easy default options are good enough you don't need to sweat. We make heavy use of disjoint unions, and while the simple case here too is easy, some things that we do - although they still are very simple on the Javascript side - are hard on the type checker (Flow in this case). > TypeScript is not a "complex dynamic" language I don't know what you read…

I don't feel defensive, but I do find your comments interesting and your experience almost diametrically opposed to mine--which is what I said.

JavaScript is quite complex and quite dynamic, but the reason TypeScript got me back into doing web stuff was, by and large, because it removes that except for in clearly delineated places (at least, once you turn on strict mode).

You're reading in some stuff that isn't intended.

Post reply on HN