Was just talking with someone the other day who used to write Haskell professionally but is now using Python. He said that in his experience when there are bugs the "blast radius" is much larger in a dynamic language like Python than in a static language like Haskell. That has been my experience as well. Something I haven't seen talked about, though, is how powerful the type system is for constraining LLMs when using…
Functional programming and reliability: ADTs, safety, critical infrastructure
131–140 of 191 posts
Re: Functional programming and reliability: ADTs, safety, critical infrastructure
#132It's acceptable to state, without evidence, that functional programming and static typing make things more reliable. But this isn't a falsifiable claim. We cannot possibly know if this is true or not. - Not all of banking and telecom use functional programming or even static typing. - Functional programming often leads to write-only incomprehensible code; the exact opposite of what you need to have a reliable system.…
> Functional programming often leads to write-only incomprehensible code; the exact opposite of what you need to have a reliable system. In what language?
… I mean, if we’re just making global assertions :)
Gimme the “write only” compiler verified exhaustively pattern matched non-mutable clump in a language I can mould freely any day of the week. I will provide the necessary semantic layer for progress backed with compiler guarantees. That same poop pile in a lesser language may be unrecoverable.
Re: Functional programming and reliability: ADTs, safety, critical infrastructure
#133Earlier quoted context omitted.
I get your point about ICFP drifting into “types, types, types.” I don’t think FP benefits are only static typing or immutability, pure-ish core/imperative shell, and explicit effects matter a lot even in dynamic languages. My angle was narrower: static types + ADTs improve the engineering loop (refactors, code review, test construction) by turning whole classes of mistakes into compiler errors. That’s not “what FP i…
Static types and ADTs are orthogonal to being FP, as Rust clearly shows. But to speak in terms of FP when those are the important things for you is just wrong since even non FP languages now have ADT, including also mainstream languages like Java, Kotlin, Dart, C# and more. Even purity is not something exclusive to FP, D and Nim also support separating pure from impure functions. And if you ask me, the reason not man…
Re: Functional programming and reliability: ADTs, safety, critical infrastructure
#134Earlier quoted context omitted.
While others have addressed the programming case for tagged unions, I want to add that, to a logician, tagged unions are the natural construct corresponding to "logical or". In intuitionistic logic (which is the most basic kind from which to view the Curry-Howard or "propositions-as-types" correspondence), a proof of "A or B" is exactly a choice of "left" or "right" disjunct together with a corresponding proof of eit…
I disagree. Something of type "A" should, according to basic propositional logic, also be of type "A or B". That's the case for an untagged union, but not for a tagged union (because of wrapping), which is decidedly illogical.
Now I do see where you are coming from; under a set-theoretic interpretation with "implies" as "subset", "or" as "union", and "and" as "intersection", the fact that "A implies (A or B)" tells us that an element of the set A is also an element of the set "A union B".
However, this is not the interpretation that leads to a straightforward correspondence between logic and programming. For example, we would like "A and B" to correspond to the type of pairs of elements of A with elements of B, which is not at all the set-theoretic intersection. And while "(A and B) implies A", we do not want to say a value of type "(A, B)" also has type "A". (E.g., if a function expects an "A" and receives an "(A, A)", we are at an impasse.)
So "implies" should not be read programmatically as a subtyping relation; instead, "A implies B" tells us that there is a function taking a value of type A to a value of type B. In the case of "A implies (A or B)", that function takes its input and tags it as belonging to the left disjunct!
Another perspective I must mention: given a proof of "A or B" and another of "(A or B) implies C", how can we combine these into a simpler proof of just "C"? A proof of "(A or B) implies C" must contain both a proof a "A implies C" and a proof of "B implies C", and we could insert into one those proofs a proof of A or a proof of B. But we have to know which one we have! (This is a very short gloss of a much deeper story, where, under Curry-Howard, proof simplification corresponds to computation, and this is another way of describing a function call that does a case-analysis of a tagged union (or "sum type").)
Now "union and intersection" types with the set-theoretic properties you are hinting at have indeed been studied (see, for example, Section 15.7 of Pierce's "Types and Programming Languages"). But they do not replace the much more familiar "sum and product types", and do not play the central role of "or" and "and" in the correspondence of programming to logic.
Re: Functional programming and reliability: ADTs, safety, critical infrastructure
#135Using a schema/spec/type library at runtime that is even more powerful than ADTs is a better investment - or to be less controversial - is an additional investment on top of types.
Yes, it means the compiler can't help you as much, but who has time waiting for a compiler anyways ;)
I find the "make illegal state unrepresentable via types" idea great for software that needs to fly a plane, but for enterprise software not so much. The cost/benefit is not justifiable.
Re: Functional programming and reliability: ADTs, safety, critical infrastructure
#136Was just talking with someone the other day who used to write Haskell professionally but is now using Python. He said that in his experience when there are bugs the "blast radius" is much larger in a dynamic language like Python than in a static language like Haskell. That has been my experience as well. Something I haven't seen talked about, though, is how powerful the type system is for constraining LLMs when using…
Interesting experience and perhaps not entirely surprising given that type-hole driven development was already a thing prior to LLMs. Like how many ways are there to implement "[a] -> [b] -> [(a,b)]", let alone when you provide a vague description of what that is supposed to do.
Re: Functional programming and reliability: ADTs, safety, critical infrastructure
#137Earlier quoted context omitted.
The String|null example is just a nullable type; it's not an interesting use of unions either way. The conversation starts when it's Foo|Bar|Baz I'm unfamiliar with typescript, so in that language I don't have an opinion either way, but in C, you pretty much always want the tag
C doesn't support any untagged unions (or intersections) in the modern sense. In a set-theoretic type system, if you want to call a method of Foo, and the type of your variable is Foo|Bar|Baz, you have to do a type check for Bar and Baz first, otherwise the compiler won't compile.
If I have an untagged union in , and I'm iterating over an array of elements of type `Foo|Bar|Baz`, and I have to do a dynamic cast before accessing the element (runtime typecheck) .. I believe that must actually be a tagged union under the hood, whether or not you call it a tagged union or not... right? ie. How would the program possibly know at runtime what the type of a heterogeneous set of elements is without a tag value to tell it?
Re: Functional programming and reliability: ADTs, safety, critical infrastructure
#138Earlier quoted context omitted.
The String|null example is just a nullable type; it's not an interesting use of unions either way. The conversation starts when it's Foo|Bar|Baz I'm unfamiliar with typescript, so in that language I don't have an opinion either way, but in C, you pretty much always want the tag
> but in C, you pretty much always want the tag We aren't discussing unions in memory layout, but in type systems. This also clearly indicates you aren't qualified for this discussion.
Re: Functional programming and reliability: ADTs, safety, critical infrastructure
#139Was just talking with someone the other day who used to write Haskell professionally but is now using Python. He said that in his experience when there are bugs the "blast radius" is much larger in a dynamic language like Python than in a static language like Haskell. That has been my experience as well. Something I haven't seen talked about, though, is how powerful the type system is for constraining LLMs when using…
Amen. I've been coding a big hobby project in Rust since July, after having spent years using Haskell for such things. I chose Rust because the primary DB I wanted to use (TypeDB) only had drivers for Rust and Python at the time. Rust is popular relative to Haskell, so I thought others might be more likely to sign on, and the type system seemed almost as expressive. But since purity is not encoded in Rust's type syst…
Actor-like patterns makes this nice. Message-objects can be passed to/from a module with db-access or other io.
Re: Functional programming and reliability: ADTs, safety, critical infrastructure
#140Earlier quoted context omitted.
I should add a few more things: much of how I got here was exposure to Facebook's culture. Move fast and break things. React with prop types. Redux. Immutable.js. I did UI there on internal tools for datacenter operators and it was a drinking-from-the-firehose experience with exposure to new programming philosophies, tools, and levels of abstraction and refactoring velocity beyond anything I had previously encountere…
Yes, I am wondering if opaque types would be difficult to implement somehow in TypeScript? It should really be part of TypeScript if at all reasonably possible.