Existential Type
existentialtype.wordpress.com · Personal blog · on HN since 2011
Robert Harper, a Carnegie Mellon professor, writes about programming language theory, type systems, modules and parallelism.
What HN saysHN commenters cite it as the classic argument that dynamic languages are static languages, and enjoy his opinionated posts on ML versus Haskell.
157HN people shared it
91linked it in comments
88stories submitted
1.2Kstory points
4 months agolast shared
2011people per year2026
Most-shared posts
- 1Dynamic languages are static languages40 people · 109 points · first shared 2011 · 66 comments on HN
- 2Parallelism is not concurrency18 people · 119 points · first shared 2011 · 41 comments on HN
- 3Boolean Blindness18 people · 9 points · first shared 2011 · discussion on HN
- 4Modules Matter Most13 people · 63 points · first shared 2011 · 26 comments on HN
- 5The Holy Trinity: Logic, Languages, Categories (2011)12 people · 121 points · first shared 2011 · 49 comments on HN
- 6What, If Anything, Is A Declarative Language?11 people · 12 points · first shared 2013 · 1 comments on HN
- 7The Point of Laziness (2011)9 people · 76 points · first shared 2011 · 8 comments on HN
- 8Existential Type, new blog by Bob Harper (of CMU) on programming languages7 people · 2 points · first shared 2011 · discussion on HN
- 9Of Course ML Has Monads5 people · 51 points · first shared 2011 · 16 comments on HN
- 10Parallelism and Concurrency, Revisited5 people · 2 points · first shared 2014 · discussion on HN
- 11Persistence of Memory4 people · 17 points · first shared 2011 · discussion on HN
- 12Structure and Efficiency of Computer Programs4 people · 5 points · first shared 2014 · discussion on HN
- 13Sequentiality as the Essence of Parallelism4 people · 5 points · first shared 2017 · discussion on HN
- 14Yet Another Reason Not To Be Lazy Or Imperative4 people · 5 points · first shared 2012 · 1 comments on HN
- 15Teaching recursion and induction at CMU: program == proof4 people · 3 points · first shared 2011 · discussion on HN
What HN people wrote when they linked it
spacemanaki · 2012-07-15
> It means the course wasn't about programming.
Parent of your comment might have been talking the Structure and Interpretation of Computer Programs. Likely it needs no introduction, but it is absolutely about programming, and goes right down the rabbit-hole to implementing interpreters, virtual register machines, and a compiler for said machine. Yes, the first couple of chapters is mostly purely functional, but that doesn't detract from the rest, which includes mutable code as well.
Really, I don't know why you're so hostile to this pedagogical approach. Do you have experience with teaching CS and/or programming, and have found using C or assembly or following some kind of Java school curriculum more effective? Have you found teaching functional programming first deficient? Or maybe you're looking at this from the perspective of an employer and have had to deal with hiring new grads who are brain damaged by functional intro CS classes?
I, for one, welcome this kind of experimentation or change of pace on the part of CS educators like Robert Harper at CMU (http://existentialtype.wordpress.com/). It can't be worse than what I had (mediocre, big box state Java school)
YorkshireSeason · 2022-01-27
If you are interested in Harper's opinions of dynamically typed languages, I recommend his blogpost "Dynamic Languages are Static Languages" [1]. It was also discussed on HN [2], in the context of a blogpost of Tratt's, defending dynamically typed languages.
[1] https://existentialtype.wordpress.com/2011/03/19/dynamic-languages-are…
[2] https://news.ycombinator.com/item?id=8206124
darksaints · 2020-10-26
One of my favorite rants on the practicality of Haskell vs ML.
https://existentialtype.wordpress.com/2011/05/01/of-course-ml-has-mona…
Ericson2314 · 2020-09-27
No "dynamically typed" is an oxymoron, and untyped or "unityped" is correct.
Please read https://existentialtype.wordpress.com/2011/03/19/dynamic-languages-are… the classic take-down of this mistake.
cannam · 2017-06-14
"Haskell is, in my view, the world’s best imperative programming language, and second-best functional language" - Robert Harper (https://existentialtype.wordpress.com/2011/04/09/persistence-of-memory…
hackermailman · 2017-04-24
I've seen more university calendars these days copy CMU and add functional programming like SML as the new preferred intro course, esp European universities it really is probably one of the best student languages for understanding/reasoning about large programs by using types and it puts everybody on equal footing since normally most first year students have zero exposure to functional programming. https://existentialtype.wordpress.com/2011/03/21/the-dog-that-didnt-ba…
dwenzek · 2016-11-09
I agree.
The post's tone is a bit harsh and could be more respectful.
After all, there is no consensus for type classes,
[ML's modules being an alternative](https://existentialtype.wordpress.com/2011/04/16/modules-matter-most/)
Nonetheless, the post is interesting and worth the reading because it raises true questions. For instance, I was surprised to learn that adding a field to an extensible record was no more a feature.
vog · 2016-10-05
This is a very good explaination of that topic, creating languages which are not turing complete but still useful.
Also, I recommend reading Harper's throughts about it:
"Old Neglected Theorems Are Still Theorems" https://existentialtype.wordpress.com/2014/03/20/old-neglected-theorem…
It also reminds me of the NASA coding standards, rule 4:
"All loops must have a fixed upper-bound", see http://pixelscommander.com/en/javascript/nasa-coding-standarts-for-jav…
(Related HN discussion: https://news.ycombinator.com/item?id=8856226)
dwrensha · 2016-07-16
I recommend Bob Harper's essay on "boolean blindness": https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/
An excerpt:
> The problem is computing the bit in the first place. Having done so, you have blinded yourself by reducing the information you have at hand to a bit, and then trying to recover that information later by remembering the provenance of that bit.
jonsterling · 2015-10-02
What a lovely post! Still true.
Another great post that he links to is Persistence of Memory (https://existentialtype.wordpress.com/2011/04/09/persistence-of-memory… where he talks about persistent and ephemeral data structures, and gives a convincing argument for the former.
taeric · 2014-11-30
Yeah, I chose a somewhat poor example. My main point was that order matters, you have to do A before B. You can not do them at the same time, or something different happens. (Contrasted with a language like VHDL where everything typically happens at the same time.)
Simply put, functional is not necessarily the opposite of imperative.
I took to googling to see if someone had made my point better already. The best I found quickly is this[1]. It is a good read. As it points out that we are most likely both stuck on different numbers in the "opposite of imperative" definition world.
I will say that throwing out mutability with the bathwater is perhaps the single most frustrating thing with most functional advocacy.
[1] https://existentialtype.wordpress.com/2013/07/18/what-if-anything-is-a…
hyperpape · 2014-08-21
This is not precisely about Tratt's response, but there was a great discussion on another Bob Harper post where Matthias Felleisen argued that while dynamic languages are semantically unityped, at the level of pragmatics (in the linguistic sense) they allow the programmer to freely mix various implicit type disciplines (http://existentialtype.wordpress.com/2014/04/21/bellman-confirms-a-sus… The cost is of course that the programmer gets essentially no assistance in verifying that their implicit types are consistent.
gabriel · 2014-08-08
I had the same thought. Harper has lots of interesting posts on his blog: http://existentialtype.wordpress.com/ (not to mention his research).
I was delightfully surprised running into this comment in a footnote :)
Here's the direct link to Harper's comment: http://www.pl-enthusiast.net/2014/08/05/type-safety/#comment-500
The way that Harper talks about types, such as, "It is not a matter of opinion whether an untyped language is unityped, it is a matter of fact." gives me a different perspective when I program in a language that is effectively unityped.
chongli · 2014-01-13
That's not quite true: there are many types, but the type checking is delayed into run time.
Runtime checks are not type checks[0], they are class checks.
[0]. https://existentialtype.wordpress.com/?s=dynamic+typing
dmunoz · 2014-01-12
The linked course pages contains a good synopsis, but Robert Harper's own blog post "What’s the big deal with HoTT?" [0] gives a wider view about its motivation and history.
Another two pages with worthwhile information on the HoTT book are [1] and [2].
[0] http://existentialtype.wordpress.com/2013/06/22/whats-the-big-deal-wit…
[1] http://golem.ph.utexas.edu/category/2013/06/the_hott_book.html
[2] http://math.andrej.com/2013/06/20/the-hott-book/
qznc · 2013-02-21
Agreed.
I tried to benchmark the context switching of user-level threads vs kernel-level threads [0]. Specifically, libtask vs pthread. I assumed, pthread_yield would be very expensive, because it has to do a syscall into the kernel. Something like an order of magnitude or two. Interestingly, with two threads switching back and forth was only two times as slow as the user-level threads. Linux futexes seem to be really clever. Use them!
On the other hand, pthread_yield scales linearly, while libtask has a constant time yield. So for concurrency without parallelism [1] and lots of threads, the libtask library can be recommended.
[0] https://bitbucket.org/qznc/switchcost/src
[1] http://existentialtype.wordpress.com/2011/03/17/parallelism-is-not-con…
noblethrasher · 2012-08-16
The author is an accomplished computer scientist in his own right but he's recently become more (in)famous for his critiques of Haskell in his new blog: http://existentialtype.wordpress.com/
Here's a recent HN discussion: http://news.ycombinator.com/item?id=4380900
dons · 2012-04-13
great to see this coming from non-functional language folks (after years of banging out about it in Haskell land -http://ghcmutterings.wordpress.com/2009/10/06/parallelism-concurrency/ )
Of course, concurrency is not the end of things. Deterministic parallelism is a beautiful model for making things faster, easily. So you need that in your language somehow too.
Edit: there's a cite for Bob Harper on this, http://existentialtype.wordpress.com/2011/03/17/parallelism-is-not-con… , which was a bit later than Simon's post.
jimwise · 2011-04-14
For more on the "Functional Patters are Concurrency Patterns" idea, see Bob Harper's recent post on the subject:
https://existentialtype.wordpress.com/2011/03/17/parallelism-is-not-co…
(The whole blog is worth reading; Harper is basically giving a blow-by-blow as CMU rolls out it's new functional-programming-first CS curriculum.)
primodemus · 2011-04-13
Robert Harper from CMU, eloquently expresses the same notion:
"One of the classic pitfalls of teaching recursion is to try to explain it by referring to some mysterious entity called a “stack” that is absolutely invisible in the program you write. There’s a long song and dance about “frames” and “procedure calls” and “pushing” and “popping” things on this “stack” of which the professor speaks, and no one understands a damn thing. It all sounds very complicated, and impressive in a way, but if there’s one thing people learn, it’s to stay the hell away from it! And in doing so, students are robbed of one of the most powerful and useful programming tools available to them, the key to writing clean, reliable code".
more: http://existentialtype.wordpress.com/2011/03/21/the-dog-that-didnt-bar…
joelburget · 2011-04-12
I've been reading some blog posts here http://existentialtype.wordpress.com/ about the curriculum at Carnegie Mellon and I've been very impressed. I can't believe they're phasing out object-oriented programming! Here the faculty seem to think object-oriented is the only way. Actually I can't think of any functional programming we've been introduced to. (Or any other paradigm for that matter)
ltr_ · 2023-12-18
I agree with your sentiment and resonate with some of my opinions on languages (been reading about TT and abstract math in general for a while as a hobby)
my opinions so far (subject to change as i read more):
dynamic typing = just one type [0]. yes, good to test ideas quick, to develop quick gigs that i don't care about and tiny snippets/scripts, i use js for that.
gradual typing = guaranteed mess evolving large code bases, I guess the gradual typing thing in practice never happen and when it happens your IDE becomes red and your compiler errors explode, i don't recall where i read about that but it made sense to me, i used groovy to take advantage of the optional typing but i was the only dev in that project.
sound type system + parametric polymorphism = the best thing around, although i prefer to have explicit type annotations.
no formal math object behind a language = the language does not exist, just , absurd rules ,idioms and syntactic mess that you have to remember and tied to specific monkey patched implementations to compensate incoherent foundations, sadly unavoidable, as most, if not all popular languages do not exist,.
Yes, I've been reading Harper a lot.
[0] https://existentialtype.wordpress.com/2011/03/19/dynamic-languages-are…
edit: formatting
Kranar · 2021-10-18
There's this pretty abstract idea of boolean blindness, which basically boils down to the idea that a boolean by itself must always be associated with an interpretation and said interpretation is external to the boolean. Afterall a boolean by itself is just a single bit of data, 0 or 1, how to interpret that bit is entirely independent of the bit itself.
This means anytime you operate on a boolean, you must somehow recover its interpretation from somewhere, and the argument is that such recovery is error prone and fragile.
The preferred way, presumably, is then to encode the interpretation directly into the type, so for example you use an enum along with pattern matching, or you write a type that wraps a boolean with some value (like a Maybe/Optional type). In effect anytime you have a boolean, you also carry with it its interpretation side-by-side so you don't need to go figuring out how to recover it.
This article goes into it in more depth:
https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/
I personally think it's insightful and useful, but there are also downsides to it as well, for example when you need to operate on multiple booleans, it becomes unergonomic and bloated to deal with pattern matching over multiple enums or having to write out a lot of redundant code instead of operating on boolean operators.
Basically consider these two options:
Option 1: boolean blindness.
bool isEven(int value);
...
if(isEven(x))
{
…
chriswarbo · 2021-04-15
Sounds like you may enjoy Algorithmic Information Theory.
In particular, Solomonoff Induction is the most information-efficient method of inducing computable rules from observations https://en.wikipedia.org/wiki/Solomonoff%27s_theory_of_inductive_infer…
It uses Bayes rule to update hypotheses based on observations; and its initial hypothesis is the "universal prior", which assigns probabilities to observations based on how likely they are to be output by a randomly-generated computer program (more specifically, an infinite sequence of uniformly-random bits, interpreted as a self-delimiting, Turing-complete language). The universal prior is uncomputable, but has been proven to dominate all computable probability distributions. Whilst computable approximations of the universal prior, like https://en.wikipedia.org/wiki/Speed_prior , aren't as information-efficient, they are more time-efficient, and approach the universal prior when given more time to run (they're identical in the limit of using infinite time).
This is relevant for Occam's Razor, since the universal prior itself is dominated by the shortest program that outputs an observation, i.e. the best prediction we can make about what any computable system will do next, is to look for the simplest description of (AKA shortest program outputting) everything we've seen it do so far, and make a prediction based on what that program does next. When we say the shortest program "dominates", this means that even if every…
panic · 2017-07-25
Here are a bunch of blogs from my RSS reader that I think are worth reading. Some of them haven't updated in a while, but the archives may be worth a look anyway.
* Blogs with a math focus:
http://blog.sigfpe.com
http://bit-player.org
http://mathr.co.uk/blog/
https://www.johndcook.com/blog/
* Blogs with a programming languages focus:
https://existentialtype.wordpress.com
https://bluishcoder.co.nz
http://blog.ezyang.com
http://akkartik.name
http://lambda-the-ultimate.org
http://mrale.ph
* Blogs with a UI design focus:
http://www.brandonwalkin.com/blog/
http://ignorethecode.net/blog/
http://interuserface.net
* Blogs with a graphics / 3D rendering focus:
http://c0de517e.blogspot.com
http://diaryofagraphicsprogrammer.blogspot.com
https://directtovideo.wordpress.com
http://graphicrants.blogspot.com
http://www.reedbeta.com
http://www.realtimerendering.com/blog/
https://blog.demofox.org
http://eelpi.gotdns.org/blog.wiki.html
* Other interesting / more general programming blogs (many of these have a "systems" focus):
http://danluu.com
http://ewontfix.com
http://chneukirchen.org/blog/
http://neverworkintheory.org
http://apenwarr.ca/log/
https://www.snellman.net/blog/
https://www.pvk.ca
http://psy-lob-saw.blogspot.com
https://randomascii.wordpress.com
http://fastcompression.blogspot.com
https://fgiesen.wordpress.com
http://blog.plover.com
http://chneukirchen.org/trivium/
http://rachelbythebay.com/w/
coldtea · 2016-09-22
>I don't get this. Most of the known refactorings can't be easily implemented by IDEs so you're left with the trivial ones like renaming or moving things.
First, the trivial ones are great and useful refactorings too -- and still difficult in dynamic type systems.
Second, static types also benefit the more difficult refactorings that you still have to do manually, by giving you compiler errors and warnings when you botched them at least at the type level. With dynamic languages those need to be done both 100% manual and with no aid.
Third, static languages are a superset of dynamic typed languages, so they can do everything the latter can do, while the inverse is not true.
You can have a "var" or "variant" etc type in a dynamic language that lets you code exactly like in a dynamic typed language where you want it.
(In fact dynamic typed languages are just static type languages with a single type: https://existentialtype.wordpress.com/2011/03/19/dynamic-languages-are… ).
catnaroek · 2016-06-10
All of the proposed solutions are deficient:
> Pattern 1: Boolean Params
This solution suffers from what we typeful programmers call “Boolean blindness”: https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/ . When you compute a bit, what you are actually interested in is the meaning of the bit, which isn't included in the bit itself. For example, if the bit is set, then “x” is less or equal than “y”; if it's unset, then “x” is greater than “y”.
> Pattern 2: Switch to Polymorphism
Dynamic dispatch (what the author wrongly calls “polymorphism”) can be used for open-ended case analysis. But it suffers from two drawbacks: (0) Unless you have multimethods, case-analyzing two or more values at the same time is a bitch! (1) Even if you do have multimethods, the open-ended nature of this whole business makes static exhaustiveness checking (making sure that no case is missing) impossible.
> Patte[r]n 3: NullObject/Optional over null passing
Null objects are still falling back to pattern 2, and optionals are severely underpowered in languages without pattern matching and compile-time exhaustiveness checks. For instance, one of my favorite patterns is implementing operations (say, “merge”) on non-empty collections, then extending them to possibly empty ones:
(* pe = possibly empty *)
datatype 'a pe = Empty | Cons of 'a
(* extend a merge operation on non-empty collections
* to possibly empty ones *)
fun pointed _ (xs, Empty) = xs
|…
vilhelm_s · 2015-08-03
I think there is no difference between constructive and classical logic here? The proof of "the powerset of the natural is uncountable" (or equivalently, expanding out the definition of uncountability, "there does not exist a bijection between N and P(N)") is constructive, and will hold just as well in intuinistic logic. You can't get away from uncountable sets.
On the other hand, you could prove a metatheoretic result, constructing a model which only contains sets which are forced to exist by some finite formula (and therefore the model is countable). But that you can do in ordinary classical set theory also (the Löwenheim-Skolem theorem, Gödel's constructible universe).
I guess this is analogous to how, in constructive logic every function is computable, but it is not possible to internalize this fact as an axiom in the logic. (https://existentialtype.wordpress.com/2012/08/09/churchs-law/)
saosebastiao · 2015-07-22
One of my favorite monad rants
https://existentialtype.wordpress.com/2011/05/01/of-course-ml-has-mona…
My point is that the ML module system can be deployed by you to impose the sorts of effect segregation imposed on you by default in Haskell. There is nothing special about Haskell that makes this possible, and nothing special about ML that inhibits it. It’s all a mode of use of modules.
So why don’t we do this by default? Because it’s not such a great idea. Yes, I know it sounds wonderful at first, but then you realize that it’s pretty horrible. Once you’re in the IO monad, you’re stuck there forever, and are reduced to Algol-style imperative programming. You cannot easily convert between functional and monadic style without a radical restructuring of code. And you are deprived of the useful concept of a benign effect.
The moral of the story is that of course ML “has monads”, just like Haskell. Whether you want to use them is up to you; they are just as useful, and just as annoying, in ML as they are in Haskell. But they are not forced on you by the language designers!
tel · 2015-02-25
"Modularity" is nearly defined by the ability to forget certain details of an interface so as to leave freedom to change the underlying details while maintaining the behavior at the interface (Reynold's Abstraction Principle). In almost the same breath one would declare that types are a primary mechanism to achieve this. [0]
Type structure is a syntactic discipline for
enforcing levels of abstraction.
Modularity is more or less required in order to take a stab at defining or talking about composability, but is "good" modularity necessary (or sufficient) for achieving composability?
I don't have a bulletproof argument here, but essentially I'd like to say that greater modularity allows you to forget inessential details and subsequently increase the surface area with which you can compose your modules.
So finally, we come to generics as a powerful tool for using types to erase inessential details. Generics essentially operate via providing a new logical structure to types, the ability to introduce and operate sensibly over type variables. So I would argue that a type language without generics is much like a programming language without variables [1]. You are perhaps not completely crippled, but pretty close.
So, my argument is something like "without generics your type language is crippled so as to make control of modularity very weak which will prevent you (syntactically) from ensuring composability".
The "(syntactically)" bit is important since, as we all know,…