Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This seems like a more personal account of the ACM article they published [1]. In both they recognize that they didn't make a great new programming language in terms of a language specification but instead did a great job building up all the things around programming languages that may end up being even more important.

In the submitted article they talk about inventing an approach to using interfaces and also an approach to concurrency. Go routines are identical to Haskell threads and interfaces are very similar to Haskell typeclasses (now that they support generic arguments). Haskell's preceded Go- it's interesting to see procedural programmers independently discover the power of ideas from functional programming.

Go's one language innovation is to not require an interface implementation to declare the interface it implements. This is awful from a safety perspective but in practice it causes few issues and gets rid of awful circular dependency issues experienced in Haskell and now Rust.

[1] https://cacm.acm.org/magazines/2022/5/260357-the-go-programm...



I think you're understating how important the fact that interfaces are structurally typed is to the overall effect of the feature on the language and—even more—its idioms and ecosystem.

Go would be a deeply different language if types had to declare the interfaces they implement ahead of time. It's one of Go's main distinguishing features (or at least was until TypeScript came out and also had structurally typed inferfaces, for different reasons).


> Go would be a deeply different language if types had to declare the interfaces they implement ahead of time.

GP literally mentions haskell which uses nominative typing and does not require types declaring the interfaces they implement (typeclasses they instantiate) ahead of time.

If anything, Go's solution is worse because you have to conform the interface you declare to whatever already exists on the type. Type classes make the "type class interface" independent from the underlying type. And then it turns out Go's structural interfaces also play hell with generics, leading to the current... thing.


My understanding is that in Haskell, all instances of type classes are explicitly declared. They don't have to be declared at the type declaration, but they must be explicitly declared. Unlike Rust, Haskell does allow orphan instances, so you can approximate some of the flexibility of structural typing, but it's still not structural like interfaces are in Go.

That's a significant difference in the design space. And, in particular, it makes generics harder. With explicit instance declarations, you have a natural place to define the type parameters of the instance itself and then specify how those map to the type arguments of the type class being implemented. With implicit interface implementations, there's no place for association to be authored.

I'm not saying Go's solution is better or worse, just that it's not them half-assed cribbing type classes. It's a deliberately designed different feature.

(My actual opinion is that I think interfaces in Go are more intuitive for users and easier to learn and use, at the expense of losing some expressiveness for more complex cases. Whether that's the right trade-off depends a lot on the kinds of programs and users the language is targeting. In the case of Go, I think that trade-off makes sense for their goals.)

I get so tired of functional programmers claiming to have invented everything first and assuming that what other languages do are just failed imitations instead of deliberate differences with important subleties they are overlooking. In particular, in these kinds of discussions, the "Haskell/Lisp/Smalltalk did it first" folks rarely take into account trade-offs, usability, or context when evaluating features.


We can't lump Lisp and Haskell into the same category. Whenever Lisp did something first, it was always easy to understand and use, compared to the twisted reinventions. The reinventions are Jack Skellington's imitation of Christmas.

About the only criticism you could lob at the Lisp original feature would be some low-brow grumble about parentheses.


> it was always easy to understand and use

Yes, because naming core operations in the language after assembly instructions in an ancient IBM vacuum-tube computer because they are incidentally how those operations happened to have been implemented once is the height of clarity.

:D


We have had synonyms for those two functions for decades. (Though not always for functions whose names are derived from those.)

Can we lay this issue to cdr?


Amazing! With jokes like this you'll really get a car in the world :)


I belong to an elite group of Lisp jokers. We believe our cadre is second to nil.


> Go's one language innovation

Structural typing is already more than 25 y.o., and was already used e.g. in OCaml and Scala.


> Go's one language innovation is to not require an interface implementation to declare the interface it implements.

Uh? How is that innovation? 100% of mainstream languages that I can think of that predate Go do this.

Can you name one programming language that we should care about which, once you define an interface, FORCES YOU to provide an implementation of said interface?


The point is that in most languages something doesn't implement an interface unless it declares that it does so; in Java or C# if you don't explicitly write "extends Writer" then your type doesn't implement Writer, even if you implemented all the methods of Writer. Whereas Go offers something similar to e.g. Python's behaviour where things are "duck typed": you don't have to explicitly reference a particular interface, you just implement the right methods. Of course in (traditional) Python that works because the language doesn't have real ("static") types at all. Having "static duck typing" is pretty rare - TypeScript now has it (and Python itself sort of has it), but when Go did it it was something that was pretty much new for mainstream languages.

(IMO it's a misfeature; having explicit interfaces communicates intent and allows you to do things like AutoCloseable vs Closeable in Java - but that's a matter of judgement)


> The point is that in most languages something doesn't implement an interface unless it declares that it does

But that's not a requirement. Haskell did nominative "interfaces" (typeclasses) and post-creation conformance 20 years before Go happened.


> Haskell did nominative "interfaces" (typeclasses) and post-creation conformance 20 years before Go happened.

Not the same thing, yes you can have orphan instances (with a flag) but you still need an explicit typeclass instance somewhere. Whereas Go interfaces are structural rather than nominal. (And much as I might wish otherwise, Haskell barely qualifies as a mainstream language)


I think you misread the sentence you quoted.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: