Hacker News new | ask | show | jobs
by i_s 3943 days ago
Types do have a lot of benefits but they also come with a big cost: some programs are very hard to express in modern type systems. For example, consider a pattern that is becoming more common today in UI programming (even in plain javascript): keeping your UI in one big tree data structure, and then working on arbitrary paths (represented by a sequence of keys) into that data structure. That is not a pattern you can encode in a type system.

Types also come with a lot of inherent complexity that you don't get with dynamic programs. Recently, I wrote a Type Provider for web Routing in F#, and it is orders of magnitude more complicated than what a dynamic approach would have been. It is nice that it is not possible to express a program that uses route parameters the wrong way, or provide a route that is unreachable, etc, but it takes a lot more work than a dynamic version with no such safety.

One domain where I think static typing is worth it is for parsing. After having used FParsec to parse a structure, and also having tried it dynamically, I felt the static typing added little complexity for all the safety it brought, so it was very much worth it. But there are also some dynamic parsing libraries that much easier to get started with, such as Instaparse, so YMMV.

3 comments

Types + pattern matching -- best combination for working with trees.

I'm not sure if there's a library in F# similar to HXT, but in Haskell, working with large xml structures is a breeze.

I use a pattern matcher that can match against types in Scheme, a language without static typing. Static types are just not the crucial feature that some people make them out to be. I believe this criticism of Pascal and C from SICP applies to other languages with static types (sans the pointer stuff):

    Pascal and C admit structures whose elements are structures. However,
    this requires that the programmer manipulate pointers explicitly, and
    adhere to the restriction that each field of a structure can contain
    only elements of a prespecified form. Unlike Lisp with its pairs,
    these languages have no built-in general-purpose glue that makes it
    easy to manipulate compound data in a uniform way.
With static typing, it's also difficult to write procedures that operate on arguments of which the type is none of the procedure's business.

https://sarabander.github.io/sicp/html/2_002e2.xhtml#FOOT73

Well, I was definitely not mentioning Pascal and C. Haskell's type system is much easier to work with.

The thing is that any operation you are using on those arguments (of which the type is none of the procedure's business) can be described by an interface which the argument implements.

You're much safer knowing in compile time that the operations you'll use will be valid, instead of hoping something doesn't crash in runtime.

There is also zippers
That pretty much describes my Angular data models, yes. My internal helper functions get passed sub-structures from the model, but Angular bindings get strings like "top.area.sub.fld" to name a variable.

Doubtless, there's another way to do this without a global / dynamic data tree, but this is working, at least for me.

So use F#'s dynamic typing parts? Or make everything obj and cast away? Unless most solutions don't work with types then it seems that you're better off having them in the language and using escape hatches as necessary.