5 ms·
The inference example is actually a good illustration for why you want to add types to a function's signature. As the author mentioned, a machine can look at h
by ahoge 12y ago
The inference example is actually a good illustration for why you want to add types to a function's signature.
As the author mentioned, a machine can look at how the arguments are used and make some educated guesses. The big problem is that humans have to do the same.
That's why I like optional types à la Dart. Not only do they help with static analysis, they also act as documentation.
With a good editor, this documentation is right at your fingertips. When you type a function's name, a call-tip will remind you of the expected arguments. If you've added type annotations, the types will be there, too.
- DanWaterworth 12y ago> a machine can look at how the arguments are used and make some educated guesses. The big problem is that humans have to do the same. Why? Just get the machine to do it. It's like when you see programmers doing arithmetic in their heads. "You're sitting in front of a glorified calculator!"
- falcolas 12y ago> Just get the machine to do it. Exactly. Many people already use IDEs, or programs which provide auto-completion or hinting of the types a function accepts when writing out a function name - the type does not need to be explicitly written for the machine to identify the type of the function.
- xxgreg 12y agoWhat types does the following function expect for the arguments a and b, and what type does it return? What should an IDE tell the user about the types of a and b in the completion popup? function foo(a, b) { return a + b; }
- the_af 12y agoIn some static languages, the inferred type for a and b could be Numeric, and foo's type could be: (Numeric, Numeric) -> Numeric Which seems good enough to me. But what if + is also String concatenation? Or any other overloading of "+". Then maybe the type of a and b is Something_that_can_be_+ed. The user can then think "ok, I'll pass a couple of Ints to obtain an Int, or a couple of Strings to obtain a String!". This also seems useful to me.
- xxgreg 12y agoNow consider the following buggy code: var price = document.querySelector('input#price').value; // "10" var tax = document.querySelector('input#tax').value; // "1" var total = foo(price, tax); // "101" This will concatenate two strings together, even though the author intended to add two numbers. If the foo function had been annotated as numeric the IDE could have provided a warning about the incorrect types and put a squigly line under foo. I find this type of fast feedback improves programmer productivity. It means that you get warned straight away, and don't have to do a trip through the debugger to find the problem. Just because the compiler can infer that a specific type could be passed to a function, that does not mean that the developer intended that function to be used with that type.
- the_af 12y agoOh, agreed. I assumed foo was meant to be generic, i.e. useful over more types than just Int. If it was just meant to be used for Int and nothing else, it should be annotated accordingly. Otherwise the compiler, quite correctly, determines that foo is more "generally useful", which may have unintended consequences.
- renox 12y agoIn this case, the issue is with using + for string concatenation, a very bad idea IMHO.
- nine_k 12y agoNote that the interface between the machine and the human is one of the slowest. Being able to learn things about numbers, or about code, without touching the keyboard / mouse is important.
- DanWaterworth 12y agoWell have the machine annotate the code then.
- sparkie 12y agoWhat the machine annotates and what the programmer wants to read are two very different things, for we often condense some long, confusing type signatures into things we can talk about - for example, a lens. type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t If we want to compose several of these, for example, with our regular function composition operator, then we check the resulting type - it's not what you really want to see. fun l1 l2 = l1 . l2 :t fun The signature given is less than helpful - if you manage to parse it you'll probably have forgot what you were tying to do next. When all we really wanted was a signature like Lens' b y -> Lens' a b -> Lens' a y Making the machine pick the "right" representation is probably a futile task - there could be any number of ambiguous representations of the same type, but the only meaningful one is the one the original programmer intended.
- DanWaterworth 12y agoIf you follow the train of this thread, you're now arguing against type inference by sighting an example from the canonical type-inferred language.
- sparkie 12y agoI'm not arguing against type inference, I'm arguing against omitting type signatures.
- krylon 12y ago> It's like when you see programmers doing arithmetic in their heads. "You're sitting in front of a glorified calculator!" At the company where I work, most engineers have real, actual calculators on their desks. I think I even saw a slide rule once. So they sit there, sometimes, doing arithmetic on their calculators and then type the results into an Excel spreadsheet.
- ahoge 12y ago> Why? Just get the machine to do it. I meant the writing stage, not the checking stage. Imagine you don't know which type to pass. So, you'd have to pass something (null or whatever) in order to generate an error which gives you a clue. That doesn't sound very convenient. Well, the machine could check which types match that fingerprint, which might work okayish if the list isn't too long, but it won't tell you anything about the writer's intend. Is a list of doubles, a list of ints, a Float32x4List, or a Float64x2List really the same thing? What if it's actually meant to be used with something else which also supports the [] operator and whose items support the + operator. Static analysis might not be able to tell you because it doesn't know all packages in existence. That package might not have been referenced, because that's not required to use a type from that package. How does the generated documentation look like? It takes one argument "foo" which is something which has a "bar" field and a "baz" method? I'd rather have a concrete type there. "int x". Done. What if you optimize the function a bit and now the fingerprint doesn't match one or more types anymore. Was this a breaking change? Your intention didn't change. You always had one particular type in mind.
- DanWaterworth 12y agoI'd encourage you to try writing some Haskell. It's a good example of type inference that works.
- ahoge 12y agoYou didn't answer my questions. I have no doubt that untooled unitypedness can be improved upon.
- the_af 12y ago> With a good editor, this documentation is right at your fingertips. When you type a function's name, a call-tip will remind you of the expected arguments. If you've added type annotations, the types will be there, too. Without type annotations, the types will be there too for a language with type inference. The editor just has to ask the language implementation "hey, what is the type for this function?" and show the result back to the programmer.