News for hackers. Stuff that matters.
Re:Implement with Types, Not Your Brain by quickthrower2 on Tuesday June 25, 2019 @07:10PM (#20280174)
Not completely. Types are documentation. When going from JS -> TS you suddenly have the ability to create types that allow you to easily discover what is in an object. You can now confidently say foo.bar.replace(...) and know it'll work at runtime.

Otherwise you hope that someone has written in a doc somewhere that bar is a string. And judging by npm docs I've seen - that is very unlikely. So you debug at runtime, head over to the github repo, or do an console.log(typeof(... hmm!

Re:Implement with Types, Not Your Brain by Scooty on Tuesday June 25, 2019 @07:25PM (#20280308)
My biggest problem with this claim is typescript doesn't include any support for runtime type checking.

My experience with TS has been great until I need to deal with data that comes from an external system (API, client, database). Then I either have to cast the type (which can lead to bugs where compile and run time types don't match and IMO isn't an option server-side) or I have to effectively duplicate my types by writing type guard functions.

Re:Implement with Types, Not Your Brain by kyllo on Tuesday June 25, 2019 @07:52PM (#20280513)
Speaking of TS, here is a good argument for static typing:

>Change a front-end React prop, then follow static type errors through the statically typed API, into the backend, all the way down into the database where they force a change in the Postgres schema. The system won't even compile unless React can talk all the way down to Postgres.

https://twitter.com/garybernhardt/status/1140695491685933060

Re:Implement with Types, Not Your Brain by wellpast on Tuesday June 25, 2019 @09:21PM (#20281047)
You’ve just described hell.
Re:Implement with Types, Not Your Brain by wellpast on Tuesday June 25, 2019 @10:21PM (#20281333)
Okay, let me be more specific. I've built complex React apps full-stack down to Postgres and maintained them over ever-evolving/increasing product requirements. To schedule. With a tiny team, part-time dedicated. And little maintenance/defects/outages in between feature pushes.

The success here lied in using various tools, applied pragmatically at each step according to the given context. Probably the most important tool is defensive coding and building up a system from decoupled, almost visibly-correct components. Then some nice technical tools thrown in: dynamic development with hot loading, some modest storybooking of components, a repl, good backend libraries, conscious and measured unit testing, strong build/deploy/release tools.

The ability to turn on a dime and incrementally refactor things was paramount to the success and efficiency of this development.

Then someone says we need to use strong static typing. All the way. No judicious application of this tool, we'll use it everywhere. We'll make everything cohere to the type system. This is no pragmatic choice. This is religion. You know its religion because its an ideology that pervades the whole system. There is no judicious application. The extreme tax of contending with types as your system evolves is high. I've only ever seen strong typing enthusiasts deny this truth. Will one enthusiast be honest here? You can literally stand over a strong typing enthusiasts shoulder as they spend an hour running all over their system adjusting their types for one minor change in business requirements and they'll still say, "No, no, types don't cost anything..."

Re:Implement with Types, Not Your Brain by kyllo on Wednesday June 26, 2019 @01:37AM (#20282169)
You sound smart, but I don't want to have to be that smart when I'm refactoring code. I want the compiler to do as much thinking for me as possible. I want to be able to change it in one place and have type errors to remind me of any other places in the codebase I forgot to change.

Static analysis doesn't solve all your problems, but it solves enough of them to be a very useful technique.

Re:Implement with Types, Not Your Brain by wellpast on Wednesday June 26, 2019 @10:35AM (#20285386)
Static typing cannot ensure about their code what the coder can and should ensure about their code.

And often -- very often -- especially in strongly typed languages -- the static checker will reject code that is otherwise valid. First point.

Second point: Statically typed PLs (especially strongly typed ones) enforce the verifications across the code, with no (at least non-ridiculous) way for the coder to be judicious about things.

Third point: statically typed languages have weaker runtime features/abilities: polymorphism, homoiconicity, true REPL (ie true read->eval), etc.

All of these points add up to MORE cognitive complexity for the coder who is trying to develop non-trivial business applications -- not less cognitive complexity.

It's not being smart. It's learning. Once you learn algebra, say, many classes of problems without algebra would be too much cognitive complexity.

Type systems are focused on one thing: type coherence. But the real world demands runtime dynamics are what the customer is paying for; being as close to that need as possible IS lower cognitive impedance.

Re:Implement with Types, Not Your Brain by kyllo on Wednesday June 26, 2019 @01:24PM (#20287075)
"enforce the verifications across the code" is the point.

I've worked with a ton of Python code that looks like this:

    def foo(bar):
        # do stuff
        return baz(bar)
What does `foo()` return? I have to go read the body (or docstring if I'm lucky) of `baz()` to know that. And `baz()` might be another level of indirection to `quux()`. If I change what `baz()` returns, now I need to grep my codebase for all call sites of `baz()` and verify that the new return type is acceptable at each of them, and make changes if not. This is super time-consuming and error-prone, especially when a compiler (especially with an IDE refactoring tool) could do take care of it for me in seconds. It's easier if I have a good test suite, but that means I'm just implementing static type checking with runtime tests, which is more code that I have to maintain.
Re:Implement with Types, Not Your Brain by wellpast on Wednesday June 26, 2019 @02:35PM (#20287837)
You're looking at this Python code and blaming its deficiencies on lack of types. It's deficiencies are not lack of types, but lack of separation of stable vs volatile code, lack of contract specification and documentation, lack of refactoring and versioning idioms (see https://www.youtube.com/watch?v=oyLBGkS5ICk).

Why does the blame always go to lack of types?

Whether or not you have types you're still going to suffer if you don't have the other things I mention. And if you have the other things I mention then static typing become much more of a nuisance. Ergo...

Re:Implement with Types, Not Your Brain by taneq on Tuesday June 25, 2019 @10:19PM (#20281320)
Yeah, it's much better when you have to change something, and you miss an important step in the guts of the code somewhere, and the compiler DOESN'T warn you, and you continue merrily on your way, unaware that six months from now when that code path executes in the wild, it'll take your company offline for six hours while someone (probably you) sweats their box off trying to figure out what the hell just happened.
Re:Implement with Types, Not Your Brain by wellpast on Tuesday June 25, 2019 @10:33PM (#20281377)
This scares the hell out of me when I hear people say stuff like this, because if you think a type system is going to save you from your outages then that means you're not aware of a whole other more comprehensive, efficient and dynamic set of programming idioms and tools that will actually save you.

Here's how you know what I'm saying is true. Because you can go across the landscape of systems in the real world and see both crappy systems falling over and rock-solid systems humming along happily -- and the differentiation between these two categories is NOT a type system. It's one thing: it's who wrote it and what was their level of experience and what was their value system.

Re:Implement with Types, Not Your Brain by taneq on Tuesday June 25, 2019 @10:37PM (#20281400)
It's not going to automatically save me any more than a motorbike helmet will save me if I crash my bike. That's not going to stop me from wearing one, though.

I actually agree with your second paragraph, and I like to think the systems I build fall in the latter category, but I'm still not too proud to take whatever help the compiler can give me.

Re:Implement with Types, Not Your Brain by wellpast on Wednesday June 26, 2019 @11:38AM (#20286016)
You would stop wearing a bike helmet if:

   - It made you top heavy and more likely to crash
   - It reduced your speed in half
The tacit implication (or elephant in the room) when someone argues for types and the presumed safety they bring is the severe cost they impose. Now they save some costs too, for sure. But the balance that I see is far, far in the direction that they save much less than they cost. (When applied universally as they almost always are when applied.)
Re:Implement with Types, Not Your Brain by thegeomaster on Tuesday June 25, 2019 @08:05PM (#20280607)
Check out https://github.com/woutervh-/TypeScript-is. It works as a compile-time transformer which emits the type guard code for a given type and narrows down the type for you. You just call `is<T>` (returns a bool and narrows if true) or `assertType<T>` (narrows or throws an error). We've used it in production with great success.
Re:Implement with Types, Not Your Brain by munchbunny on Tuesday June 25, 2019 @07:40PM (#20280410)
It would be really nice to be able to coerce/validate incoming data (JSON I assume) at runtime against an interface definition. However, I feel like something like this goes against most of TypeScript's other stuff that aims for low cost abstractions on top of JS.

That said, even if I have to write type guards at the edges (which I'd do in JS anyway, just because you aren't using types doesn't mean you don't need to enforce schemas), I think being able to rely on compiler typechecking inside the codebase boundary is really nice for making module interactions more predictable.

Re:Implement with Types, Not Your Brain by wellpast on Tuesday June 25, 2019 @07:13PM (#20280203)
Types alone are severely insufficient documentation. That’s the refutation of the original poster’s claim.
Re:Implement with Types, Not Your Brain by dllthomas on Tuesday June 25, 2019 @09:46PM (#20281166)
Types are incomplete documentation. They may or may not be sufficient depending on the context.

There are some really great things about types as documentation, though:

1) It's machine-checked, so it's probably not out of date or mistaken, which can be worse than no documentation.

2) The interaction with my code is checked, so if I misunderstood the compiler often has my back.

3) With inference, I can often ask for docs for code I just wrote.

None of this is to say that there aren't usually other forms of documentation that should be produced.

Re:Implement with Types, Not Your Brain by perfmode on Tuesday June 25, 2019 @07:30PM (#20280337)
What are all of the things this function could possibly do to its arguments?

(a -> b -> c) -> b -> a -> c

Re:Implement with Types, Not Your Brain by quickthrower2 on Tuesday June 25, 2019 @07:45PM (#20280449)
What about String -> String-> String ?
Re:Implement with Types, Not Your Brain by dodobirdlord on Wednesday June 26, 2019 @02:13AM (#20282328)
Unless what you're doing is content-agnostic String manipulation (i.e. a function to concatenate arbitrary Strings), this type signature wouldn't make sense. And since there are only a small number of meaningful content-agnostic string manipulations, I've already got a solid guess that this is probably doing concatenation! It could also possibly be doing substitution, or a few other things, but not much before it becomes a gaping code flaw that the types in use are still 'String'. Concatenating a person's name with a country name doesn't make sense. Nor does searching for a street address in a month. A type signature like String -> String-> String should only show up down in the implementation details of helper functions, or on the signatures of content-agnostic library functions.
Re:Implement with Types, Not Your Brain by mpcjanssen on Wednesday June 26, 2019 @10:01AM (#20285075)
This could equally well be a function which takes a string and a seed and returns the hash.

The more concrete the type signatures become the less they become documenting.

A signature of a -> a defines the id function because the type is so generic. A function of String->String can do pretty much anything.

Re:Implement with Types, Not Your Brain by dodobirdlord on Wednesday June 26, 2019 @10:16PM (#20291203)
But that's exactly my point. Why would something that is a randomization seed have type "String"? Why would a hash have type "String"? Why not type Seed and type Hash?

A type signature of Seed -> String -> Hash is pretty enlightening!

Re:Implement with Types, Not Your Brain by wellpast on Tuesday June 25, 2019 @07:42PM (#20280430)
Infinite.
Re:Implement with Types, Not Your Brain by quickthrower2 on Tuesday June 25, 2019 @07:46PM (#20280457)
3 things:

1. Call the function 2. error 3. infinite recursion

Technically correct - there are infinite possible error messages.

Re:Implement with Types, Not Your Brain by im3w1l on Tuesday June 25, 2019 @08:01PM (#20280573)
It's my understanding that we have to involve a function call as a fallback, as a function call is the only way we have of producing a value of type c in the general case.

But we could potentially have some list of exceptions.

So one valid implementation would be: If c is string we always return hello world elseif a, b and c are integers we add the two ints. Elseif a and b are the same type we call the function with the argument order swapped. And finally, if none of these are the case, we call call the function with the arguments.

Re:Implement with Types, Not Your Brain by danharaj on Tuesday June 25, 2019 @08:10PM (#20280642)
In a type system like Haskell's, a function with that signature has to be unconditionally polymorphic in its variable types, so you can't have a list of exceptions.
Re:Implement with Types, Not Your Brain by dllthomas on Wednesday June 26, 2019 @03:59PM (#20288543)
If you do want to be able to list exceptions in Haskell, that's what Typeable gets you. But then the type signature is different.
Re:Implement with Types, Not Your Brain by Twisol on Tuesday June 25, 2019 @09:16PM (#20281021)
Types don’t exist at runtime in the way you’re describing. It isn’t possible to express a program that asks what type a value has.

Dynamic types are sometimes called “tags” to distinguish the case in which this information _does_ exist at runtime.

Re:Implement with Types, Not Your Brain by wellpast on Tuesday June 25, 2019 @09:11PM (#20280999)
You need to rethink your #1.

How about calling the function derivative?

Sounds like you could have used real documentation.

Re:Implement with Types, Not Your Brain by dllthomas on Wednesday June 26, 2019 @04:13PM (#20288653)
> How about calling the function derivative?

How would you write this with no constraints on the types involved?

Re:Implement with Types, Not Your Brain by wellpast on Wednesday June 26, 2019 @06:01PM (#20289697)
I hope you're not suggesting that it's impossible to write this function without such constraints. If so, you should jettison your PL as fast as you can.

In any case this is precisely the trouble I believe the typer enthusiast get into. You can keep pulling this yarn, refining your types to match the world as it exists today; meanwhile the dynamic typers forgot about this function days ago and are eating your lunch in productivity.

Re:Implement with Types, Not Your Brain by dllthomas on Thursday June 27, 2019 @01:31AM (#20291971)
> I hope you're not suggesting that it's impossible to write this function without such constraints.

To be concrete about it, that's exactly what I'm suggesting.

Please demonstrate, in any programming language, a derivative function that is parametrically polymorphic - that is, the same machine code will handle absolutely any type that's thrown at it - floating point, integral, string, function, map, set, graph, etc. I do not believe it's possible, unless you have some very different notion of derivative in mind. I would be delighted to learn it is possible, and mildly pleased to learn of a reasonable use of the phrase "derivative function" that's other than what I'm thinking and which makes sense of what you've written above.

Re:Implement with Types, Not Your Brain by dllthomas on Wednesday June 26, 2019 @11:00PM (#20291403)
Or... other people working in other languages you (obviously) don't understand have their own effective ways of working which you also don't understand.

It's a lesson that could be better understood by parts of the Haskell community, to be sure, but it's not always clear how useful a tool can be when you don't really know how to use it.

And here, you have repeatedly shown that you really don't know what you're talking about - take the opportunity to learn.

Re:Implement with Types, Not Your Brain by wellpast on Tuesday June 25, 2019 @07:46PM (#20280460)
f(+’,1,2) = “cookie”

For one.

Now tell me: are types the best documentation?

Re:Implement with Types, Not Your Brain by TheAsprngHacker on Tuesday June 25, 2019 @08:01PM (#20280572)
Maybe I'm misunderstanding what you're saying, but how on Earth would a function

    f :: (a -> b -> c) -> b -> a -> c
result in

    f (+) 1 2
evaluating to

    "cookie"
? For one, the types (obviously, to me at least) don't work out.
Re:Implement with Types, Not Your Brain by wellpast on Tuesday June 25, 2019 @09:11PM (#20280993)
Sounds like you could use some real documentation.
Re:Implement with Types, Not Your Brain by dllthomas on Tuesday June 25, 2019 @10:25PM (#20281345)
The types tell me that that's not the function in question. Type variables in Haskell mean the caller of the function gets to pick the types. That means the implementation doesn't get to - and the compiler makes sure of it.

You're pattern matching on a number and returning a string. The function might be handed a function and expected to return a file handle for all you know from inside the function.

Re:Implement with Types, Not Your Brain by nilkn on Wednesday June 26, 2019 @12:44AM (#20282000)
a, b, and c are generic types. You need to supply an implementation of f that doesn't know anything about a, b, or c. How many such implementations are there? Can you supply at least two, both of which finish running in a finite amount of time and neither of which produces any error?