Live data from Hacker News

Twenty five thousand dollars of funny money

rachelbythebay.com

141–150 of 175 posts

Re: Twenty five thousand dollars of funny money

#141

Earlier quoted context omitted.

Kotlin has type aliases. This means you can write something like: typealias Cent = Int and then use a type Cent just like you can an Int, with multiplication and everything else. More info: https://kotlinlang.org/docs/type-aliases.html

Yes, you can, but you shouldn’t to solve this problem, because typealiases aren’t new types, just–as the name suggests–aliases, so anything aliased to Int is interchangeable with Int and everything else aliased that way, so you still have exactly the same problem. Also, cents * cents shouldn’t be cents (though cents * unitless ints should be).

Good point, it doesn't solve the problem

Re: Twenty five thousand dollars of funny money

#142

One of the things I really like about f# is thar you can tag even raw numbers with types. And even multiply/divide on those types. https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...

Kotlin has type aliases. This means you can write something like: typealias Cent = Int and then use a type Cent just like you can an Int, with multiplication and everything else. More info: https://kotlinlang.org/docs/type-aliases.html

That's not quite the same thing, as in f# a unit of measure actually makes not interchangable. While a type alias, afaik, literally is just an alias, without preventing you to do something like that:

    typealias Cent = Int
    typealias Euro = Int

    SomeEuro = SomeCent
In f#, measures aren't bound to any specific numeric type either.

Re: Twenty five thousand dollars of funny money

#143
post #122

Just to say it, for measurements that take a unit I am hardcore that you should include the unit in the variable time: `timeSeconds` `distanceMeters` `amountDollars` Have unit tests and everything, but also write your code so that when someone reads it they know as precisely as possible what's going on without other documentation.

Using types that encode the units, as suggested in OP, is strictly better.

You're both right, but not all languages give you the choice. And a lot of types are implemented badly. For example as a subclass of a number class, so that `amountDollars + timeSeconds` and other nonsensical statements aren't errors.

Re: Twenty five thousand dollars of funny money

#144
Makes a good case why most programing languages should not provide simple numeric types - being the types we're so used to using that we don't even think about it. Squashing everything into one or two numeric types leaves us wide open to misinterpretation and confusion.

Instead, provide types for length, time, currency, age, angle, count, etc. And provide suitable operations on those types. Then inadvertently passing a pennies as dollars, or adding a time to a length, would be flagged as an error early.

(To my mind, the only languages that should provide a "number" type are systems specialised for mathematical use, where it's the mathematicians' fault if they shoot themselves in the foot.)

Re: Twenty five thousand dollars of funny money

#145

Makes a good case why most programing languages should not provide simple numeric types - being the types we're so used to using that we don't even think about it. Squashing everything into one or two numeric types leaves us wide open to misinterpretation and confusion. Instead, provide types for length, time, currency, age, angle, count, etc. And provide suitable operations on those types. Then inadvertently passing…

F# has units of measure types which seem fairly pleasant: https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref... along your ideas. You can also do your own version easily in something like Haskell. At first thought it'd be much more challenging in everything else assuming you don't want to encapsulate everything in voluminous custom classes or something.

Re: Twenty five thousand dollars of funny money

#146

Type systems are to programmers what dimensional analysis is to physicists.

> Type systems are to programmers what dimensional analysis is to physicists.

Dimensional analysis is to data in other domains what dimensional analysis is to data in the domain of physics.

Type systems are a tool in which dimensional analysis can be done, or, alternatively, which with which you can restrict data to be being dimensionally aware, allowing dimensional analysis to be done outside of the type system.

Re: Twenty five thousand dollars of funny money

#147
post #62

Earlier quoted context omitted.

Seriously, since everything I work in is denoted as "cents" from backend to frontend, I personally had never understood the need This matches my experience. Obviously actual strict typing has its benefits, but as far as developer ergonomics are concerned, IME you can get about 95% of the benefits just by following a convention of including unit names in identifier names. It's easy to see why this Ruby code might fail…

here it is with Go: package main type km int func (distance km) launch_rocket() {} func main() { distance_miles := 42 // type int has no field or method launch_rocket // distance_miles.launch_rocket() // this works, but is obviously wrong: km(distance_miles).launch_rocket() }

Go does pretty good with time. You could replicate that for distance, too.

Re: Twenty five thousand dollars of funny money

#148

Earlier quoted context omitted.

Nope, this will lead to the same problem that the OP has discovered, viz., that a dependency update creates silent errors. Unless the argument is a keyword, but everyone is too lazy for that.

Yeah, to me the moral of the story was write more tests.

If you encode your test in a type then you don't have to write it separately. Even in python you can use types for this sort of thing it will blow up at runtime but so will your test. Just have a US Money type that won't return a number unless you call as_cents() or as_dollars(). Now much harder to misuse.

Re: Twenty five thousand dollars of funny money

#149
post #57

Earlier quoted context omitted.

> [follow] a convention of including unit names in identifier names. appending units to identifiers helps, but it relies on a developer's eyeballs to spot any errors. It would be infinitely preferable if the type system would simply enforce this for you and developers not have to expend cycles reasoning about this stuff themselves.

If you stick to just a few units throughout the system (ideally, use a consistent base unit everywhere and convert any external measurements to it), you can avoid the rest of the problems. Static typing is great, of course, I just don't agree that this can't be solved to almost the same level with languages with dynamic typing.

The keyword is “almost”, and whether you need stricter typing depends how much you care about software correctness (or to be pedantic, the class of problems that the typing system can fix for you in the language in question).

Re: Twenty five thousand dollars of funny money

#150
post #88
post #41

Had exactly that bug in production, was using ruby on rails & active merchant, and some version change in ActiveMerchant switched from cents to dollars for one of the integrations. Our test harness didn't catch it (weird combination of reasons, too long ago for me to remember the details) & it rolled out. Shortly thereafter I get an anxious customer call that we'd charged their debit card $2500.00 instead of $25.00 a…

> Our test harness didn't catch it (weird combination of reasons, too long ago for me to remember the details) & it rolled out. This is why I'm pretty dogmatic about variable comparison in tests. This is dangerous and stuff like this has caused a lot bugs to slide though in my experience (and maybe ops): expect(account1.balance).to eq account2.balance This is safe and specifc: expect(account1.balance).to eq 2500 expe…

[deleted]
Post reply on HN