Live data from Hacker News

Why don't more languages offer flow typing?

ayazhafiz.com

61–70 of 127 posts

Re: Why don't more languages offer flow typing?

#61

Earlier quoted context omitted.

In the end, I feel like structural typing is one of those attractive nuisances. It sounds good on the outset, and it does provide a limited amount of convenience, but then it turns out not to be that convenient, and it removes a lot of safety and flexibility by taking intent out of the thing.

There is a fundamental tradeoff between cost-free upcasts and efficient layout, but languages could offer both options and many in between. IMO in general: in the face of tradeoffs, moving the goal posts to let the programmer decide is an unexplored 3rd option.

> There is a fundamental tradeoff between cost-free upcasts and efficient layout, but languages could offer both options and many in between.

Not sure what the relationship to my comment is there, this tradeoff exists in nominative land, it’s got nothing to do with structural typing.

Re: Why don't more languages offer flow typing?

#62

Contrary to what many comments here state, I don’t think this is only useful in a dynamic runtime kind-of environment. I often think I could use some form of this in Rust and/or Haskell. In a very specific way: I often want a single constructor/branch of an enum (sum type) to a be a type as well, specifically a sub-type of the full enum. So once I learn about what branch a value is, I can treat it like that and even…

Yeah this would definitely be useful in Rust. It isn't in Rust currently because enum variants aren't distinct types, but that's definitely on the to-do list. I suspect Rust will get this eventually.

Re: Why don't more languages offer flow typing?

#63

It's not really called out as such, but the C# 8 feature Nullable Reference Types is an example of deeply embedding flow typing into a language. The nullability state of a reference type can change based on many things you can do in code. It's really neat and extremely intricate.

It's exactly that.

e.g. inside "if (x != null) { }", or after "x = y ?? throw new ArgumentNullException()" then x is known not null.

C# has flow types, but only in this specific and limited way. You could say that about a lot of programming language features.

Re: Why don't more languages offer flow typing?

#64
This question actually has a simple answer:

Most languages have embraced statements over expressions for a lot of language constructs.

This causes a lot of issues:

An if-statement is in essence a function from boolean to unit/() (i.e. from a barely useful type to a type with no useful information), while an if-expressions will contain enough type information to at least provide this kind of “flow typing”, (even if it induces an amount of boolean blindness.)

It’s even worse when you get to loop-statements, which often is a function from unit/() to (unit/() | bottom/⊥), compared to a map or a reduce or fold, which again provide enough type information to provide this kind of “flow typing”.

Sometimes you will of course need to provide impure conditionals or loops, but that can be made explicit in the type system.

IMHO statements in programming languages are an anti-pattern.

Re: Why don't more languages offer flow typing?

#65

This question actually has a simple answer: Most languages have embraced statements over expressions for a lot of language constructs. This causes a lot of issues: An if-statement is in essence a function from boolean to unit/() (i.e. from a barely useful type to a type with no useful information), while an if-expressions will contain enough type information to at least provide this kind of “flow typing”, (even if it…

> Most languages have embraced statements over expressions for a lot of language constructs.

Some of the most used languages with flow typing have statements and follow them for typing, so that is emphatically not the reason.

Re: Why don't more languages offer flow typing?

#66

The answer is simple: because other languages don't need it - they have different features to deal with it. The author even mentions it: pattern matching. Just that he picks a language that doesn't support union-types. But that doesn't mean that flow typing would be necessary here - it means that the language(s) should support union-types and extend their pattern matching accordingly. In fact, I would say that flow t…

I don't think pattern matching and union-types makes narrow typing useless. Rust has both pattern matching and union types but still implements some specific forms of control-flow based typing.

For example, consider this Rust snippet :

    pub fn positive1(x: isize) -> Option {
        if x > 0 { Some(x as usize) } else { None }
    }
Unless I'm mistaken, without narrow typing, this cast would be impossible, and there would be no way to avoid the redundant runtime check caused by try_into().unwrap(), that is not even optimized unless you trick the compiler.

Re: Why don't more languages offer flow typing?

#67
post #4

This is not a complete answer, but covers some languages. If you program too exclusively in dynamically-typed languages, you can be too used to not thinking about how physically large your types are, because you work in a world where everything is boxed, and allocations so plentiful you don't even hardly have a way of thinking about them because your language does them at the drop of a hat, and so on. But there are m…

> In these languages, this sort of narrowing is a great deal more complicated, because it implies a new type, which will probably require more allocation. Flow typing need not imply any kind of "narrowing", though. It could simply endow a control-flow branch with a statically-typed proof object, asserting whatever post-conditions were established in the branch. The "narrowing" could then become a separately-coded ste…

That sounds great at the napkin-sketch level.

But if you mean what I think you mean, now your entire compiler suite needs to be reworked to change its internal concept of what guarantees a "type" has. Previously the compiler was able to assume it was a contiguous chunk of memory, but now it needs the concept of a non-contiguous chunk of memory representing a certain type, and it needs everything everywhere updated to accommodate that, and it may need to add code to make copies for things that didn't used to need to make copies if you create an array of this new type, etc. It goes on and on.

I'm not the world's expert on all this under-the-hood stuff, but there is still something to be said for learning a bit of C or something deep enough to understand how it interacts with the machine, and C probably is still the best language for this despite its manifold other flaws. There's all kinds of fun games you can play in conceptual math space to make awesome programming languages, but if you want your language to play in the "goes fast" space you will find only some of those games map to anything efficient on real machines. (There is certainly a space for languages that just provide the nice abstractions, too; between "C performance" and "Python performance" there's a lot of room to play!)

Re: Why don't more languages offer flow typing?

#68

The answer is simple: because other languages don't need it - they have different features to deal with it. The author even mentions it: pattern matching. Just that he picks a language that doesn't support union-types. But that doesn't mean that flow typing would be necessary here - it means that the language(s) should support union-types and extend their pattern matching accordingly. In fact, I would say that flow t…

I don't think pattern matching and union-types makes narrow typing useless. Rust has both pattern matching and union types but still implements some specific forms of control-flow based typing. For example, consider this Rust snippet : pub fn positive1(x: isize) -> Option { if x > 0 { Some(x as usize) } else { None } } Unless I'm mistaken, without narrow typing, this cast would be impossible, and there would be no wa…

> Unless I'm mistaken, without narrow typing, this cast would be impossible

same sized integer casts in Rusts are no-ops [0]; the conditional isn't type narrowing, it just avoids the cases where the cast would not preserve the same semantic value.

[0] https://doc.rust-lang.org/reference/expressions/operator-exp...

Re: Why don't more languages offer flow typing?

#69
post #33

Earlier quoted context omitted.

Go's interfaces are a decent 80/20 answer. You pay for them, you opt in, and they sit on type of the base type system, they aren't the primitive the entire type system is based on and they aren't what the compiler works with at the most basic level. I have on a number of occasions wished I could define an interface that could be fulfilled by a field without me having to write a method, but it's not a use case that co…

> Go's interfaces are a decent 80/20 answer. You pay for them, you opt in, and they sit on type of the base type system, they aren't the primitive the entire type system is based on That's interesting because I see them as the exact opposite. You're not saving or gaining anything of significance, and it's just increasing confusion. Penny wise, pound foolish, if you will.

I'm not sure what you mean by "not gaining anything of significance." Go without interfaces (and for simplicity let's ignore 1.18's generics for a moment) would not be a useful language at any significant scale. You'd end up with a lot of "by hand" interfaces of structs full of function pointers (or method closures), only without the compiler support.

Nor am I sure exactly what "confusion" is being increased.

Re: Why don't more languages offer flow typing?

#70

This question actually has a simple answer: Most languages have embraced statements over expressions for a lot of language constructs. This causes a lot of issues: An if-statement is in essence a function from boolean to unit/() (i.e. from a barely useful type to a type with no useful information), while an if-expressions will contain enough type information to at least provide this kind of “flow typing”, (even if it…

> Most languages have embraced statements over expressions for a lot of language constructs. Some of the most used languages with flow typing have statements and follow them for typing, so that is emphatically not the reason.

My view might of course be a bit outdated, do you have any examples?

(Specifically for this point: “and follow them for typing”)

Post reply on HN