Live data from Hacker News

Make the Type System Do the Work

nathan.ca

111–120 of 141 posts

Re: Make the Type System Do the Work

#112

This is a good trick but it needs to be used judiciously or you'll end up with lots of boilerplate. I particularly like Go's type system, though, because it makes it very simple: type celsius float64 There's no overhead and it doesn't attempt to prevent you from doing any calculations as a float64; the type checking just prevents direct assignments from a celsius type to another type.

I got annoyed with Go when I learnt how hard it is to sort arbitrary lists. Doing the following in Go is quite a pain:

scores = [{'name': 'Bob', 'score': 20}, {'name': 'Jane', 'score': 15}] scores.sort(key=lambda x: x['score'])

Re: Make the Type System Do the Work

#113
post #90
post #39

Earlier quoted context omitted.

It can make a difference due to weird ABIs. For example, in the ARM procedure call standard, 64-bit values can be returned in r0 and r1, but 64-bit structures can't (no matter whether they contain two 32-bit values or just one 64-bit value). However, I'd call that fairly niche - it's hard to imagine an application that would notice a significant performance difference.

This is very nice to know actually, and quite relevant to code I am working on right now! Disappointing though. > it's hard to imagine an application that would notice a significant performance difference. One hopes any function call made often enough to be a perf hit from this would also be designed to be easily inlined!

Scientific computing will hit this sort of problem just because the kernel is so large it actually needs to be broken into sub-procedures for icache reasons. But also, the penalty is large, because there is a full store/load cycle involved, which will clear caches and increase memory bandwidth requirements.

Re: Make the Type System Do the Work

#114

This article uses inheritance in C++ to ensure the types line-up, but I have really taken a shine to algebraic data types for my firm's data feed handlers. Here is an example in C++11 that implements a market-data spec line-for-line. #pragma pack(push,1) struct Quote { char symbol[16]; uint16_t bid; uint32_t bidsize; uint16_t ask uint32_t asksize; }; static_assert(sizeof(Quote) == 28, "Quote size wrong"); struct Trad…

That looks like an implementation of algebraic data types, written in a language that doesn't support them. "Union" ,"reinterpret_cast" -- I hope that's well tested, since the type system won't help you there!

Re: Make the Type System Do the Work

#115
post #76

"'Dog is-a Mammal' ... actually fairly sound" I disagree in the context of OOP inheritance. (This example uses shapes, because the idea of mutating mammals gets a little strange.) Let's say you have a Circle class and an Ellipse class. A Circle inherits from an Ellipse, of course, because a Circle is-a Ellipse. By specializing as a Circle, we get extra reader methods such as getRadius(). Great. But what about mutator…

The circle vs ellipse problem is rather artificial and, if anything, it shows that modeling with types and everyday intuition are two different things. If the rest of your program can handle general ellipses, it should also be able to handle ellipses having the same minor and major radius (i.e., circles). The obvious solution is to not have the Circle class and _maybe_ equip Ellipse with IsCircle() method. (Though, w…

The circle/ellipse problem is real and shows how mutability ruins people intuitions about models and relationships. Note that mutability ruins programs in the same way, introducing subtle inconsistencies and invariant violations.

Re: Make the Type System Do the Work

#116
post #73
post #49

Earlier quoted context omitted.

It's nice how in Go you can alias a type to int, yet it is its own distinct type with compile time checks and explicit conversions. Definitely takes away all the boilerplate.

> Definitely takes away all the boilerplate. Until you need to write generic code. Then it is casts everywhere and boilerplate to satisfy interfaces.

If you need generics why are you writing in Go?

Re: Make the Type System Do the Work

#117

Earlier quoted context omitted.

They couldn't do it. The compiler does static verifications that, say, a value of type Meter when divided by a value of type second results in a value of type Meter/Second, where '/' is a custom concept built into the F# compiler. The .NET runtime knows nothing about these custom types.

Yeah, that's pretty much exactly the issue I ran into. The problem is that the standard .NET type semantics can only infer "up" the inheritance hierarchy. I had gotten really close. I had types like Base Length: Base Meters: Length Feet: Length Compound Area : Compound where T: Length SquareMeters: Area SquareFeet: Area and had defined all of my math as generic extension methods of the Base class so that the types wo…

Interesting problem! I was wondering why even define things like SquareMeters, but as you say the issues is reducing the terms that have different forms but mean the same thing.

Re: Make the Type System Do the Work

#118
post #73

Earlier quoted context omitted.

> Definitely takes away all the boilerplate. Until you need to write generic code. Then it is casts everywhere and boilerplate to satisfy interfaces.

If you need generics why are you writing in Go?

I am not, left the language ecosystem before the 1.0 release.

Might consider it again if a customer requires me to use it, otherwise I am happier with other more modern languages.

Re: Make the Type System Do the Work

#119
post #117

Earlier quoted context omitted.

Yeah, that's pretty much exactly the issue I ran into. The problem is that the standard .NET type semantics can only infer "up" the inheritance hierarchy. I had gotten really close. I had types like Base Length: Base Meters: Length Feet: Length Compound Area : Compound where T: Length SquareMeters: Area SquareFeet: Area and had defined all of my math as generic extension methods of the Base class so that the types wo…

Interesting problem! I was wondering why even define things like SquareMeters, but as you say the issues is reducing the terms that have different forms but mean the same thing.

Having a SquareMeters type was meant to reduce complexity. Instead of always dealing with Area all the time, it was meant to be a shortcut.

Hrm, what about namespace aliasing? "using SquareMeters = Composite"? Since the problem is not the composition of the type but the verbosity of the deeply composited types, then perhaps it's just about making a shortcut for the name.

Re: Make the Type System Do the Work

#120
post #73
post #49

Earlier quoted context omitted.

It's nice how in Go you can alias a type to int, yet it is its own distinct type with compile time checks and explicit conversions. Definitely takes away all the boilerplate.

> Definitely takes away all the boilerplate. Until you need to write generic code. Then it is casts everywhere and boilerplate to satisfy interfaces.

>... and boilerplate to satisfy the interfaces.

Go actually provides facilities for embedding types which helps remove some of the unnecessary boilerplate from satisfying an interface.[1]

Through embedding you can leverage the implementation of an existing type to satisfy an interface w/o writing methods to dispatch to that underlying type.

[1]: http://golang.org/doc/effective_go.html#embedding

Post reply on HN