7 ms·
Strong typing is great when I've already made sense of how the logic should flow and I'm ready to solidify my work into something stable and extensible over tim
by rocky1138 9y ago
Strong typing is great when I've already made sense of how the logic should flow and I'm ready to solidify my work into something stable and extensible over time. It's not so great when I'm trying something new and am still trying to work out if what I want to do is even possible, since I find myself trying to identify the right type to use in a given situation rather than proving that I'm even able to do it. A lot of my daily work is prototyping.
- willtim 9y agoThere's no reason why static type errors can't be deferred until runtime, GHC Haskell can do this. Personally I find types invaluable when prototyping. I often fill in the implementations after I work out the types.
- shalabhc 9y agoI wish this was adopted more broadly, e.g. by Rust and other newer languages.
- oconnor663 9y agoWhat would the semantics of that be? Something like "this function contains a type error, so if you call it your code will just panic?"
- AnimalMuppet 9y agoAt it's simplest, I could see it being a compiler flag. No annotations needed. Default would be strict compile-time typing. But with a flag, you could turn type errors into warnings (and runtime panics), or even into not-even-warnings, just silence (and runtime panics).
- willtim 9y agoHaskell can defer them by producing thunks (values) containing runtime exceptions. But unlike a dynamic-only language, you still get to know about the errors at compile time, by way of a set of warnings.
- zbobet2012 9y agoLook at Idris to see how this kind of thing works. https://jeremywsherman.com/blog/2015/10/10/idris-metaprogramming-hello-world/ https://jeremywsherman.com/blog/2015/10/10/idris-metaprogram...
- ziotom78 9y agoIf I understand well, Ada packages provide the necessary architecture for this kind of stuff. A package is like a Python "module", but it is typically split in two files: a specification, just containing the declaration of all the types and functions exported by the package, and a body, which actually implements the functions working on those types. When writing a program which uses that package, if you only compile it without linking, the compiler will complain about wrong types even if no function has been implemented yet. A poor man's version of the above schema can be achieved in C/C++ as well. Just declare your functions in a header file and include it in your program, then compile without linking.
- willtim 9y agoThis is not the same thing as deferred type errors though. The programs are still type correct, it's just that some of the implementations are missing / producing errors.
- Others 9y agoIf I'm understanding what you want correctly, Rust kinda will get that once the `!` type is stable/used in type inference correctly.
- gertef 9y ago> I often fill in the implementations after I work out the types. OK, but that's the opposite of deffering type errors until runtime. Using "undefined"/bottom as the implemenation of a function is how we wrote Haskell before GHC added support for deferring type-errors.
- ORioN63 9y agoOops. I still use undefined everywhere, while my code isn't complete. Also, typed holes. Typed holes are awesome for building implementations based on types.
- willtim 9y agoYes I don't use deferred type errors much. But the parent poster wanted the option to avoid worrying about type correct programs.
- shalabhc 9y ago> Strong typing I think you mean 'static' typing, not strong? Python is already strongly typed. > It's not so great when I'm trying something new and am still trying to work out if what I want to do is even possible I completely agree here. I find it very useful when iterating to run the program and verify just the code path that gets executed, without worrying about whether the rest of the program is also correctly typed. Once I have settled on a set of types though, it would be nice if Python told me all the places that now need to be fixed up.
- msla 9y agoThe conflation between 'strong' and 'static', and 'weak' and 'dynamic', is probably terminal at this point, but maybe I can do something to, at least, explain the position of the people who don't conflate those terms: Strong typing is about creating, expressing, and enforcing a contract which determines which operations are valid on which values. Not variables, values. Having the semantics of the value in the compiler or the runtime ensures that errors are handled predictably, with explicit detection and possible reporting. Weak typing is a lack of those semantics. In the most extreme case, you have languages such as B, where the only type is the machine word, which isn't a type at all because it doesn't imply anything about semantics: You can do anything to a machine word, so nothing can possibly be invalid, so there's nothing to enforce or detect or report. Similar "size specifications", such as int, or long, or float, are only loosely describable as types for the same reason: They specify how many bits a value has, not what's valid to do to it. So a language such as Python is strongly typed because it can detect violations of the contract inherent in the types it knows about at runtime. C is less strongly typed, because, first, it focuses on its "size specification" types, and, second, you can subvert even that type system totally with nary a peep. Languages such as Ada, which inherited the "size specification" types from Algol, are only strongly typed to the extent you can augment their type system with types which are actually semantic, as opposed to size-based.
- thanatropism 9y agoHonest question: Is Python-with-type-hinting-in-function-definitions (and maybe type assertions) equally as "strong" as common style Python? It's not static typing -- it's not Haskell -- but it's already a step further. Edit: I find myself doing a lot of "assert isinstance(x,foo)".
- seanwilson 9y agoCan you give an example? I don't find this personally. I find static strong typing speeds me up because I don't have to restart the app, click some buttons etc. to figure out some code was wrong. This is true even for prototypes. Most of the time any type declarations you need are straightforward and once you know your code better you can start introducing more exotic types to capture more errors later.
- rocky1138 9y agoA really basic example would be the "as GameObject" part of this statement in C#: `GameObject gameObject = GameObject.Instantiate(MyGameObject, Vector3.zero, Quaternion.Identity) as GameObject;". It's annoying to have to type "as GameObject" when very clearly I am creating a GameObject type (the first thing in the entire statement). Programming languages should be smart enough to figure out that's what I'm trying to do rather than require me to type that out.
- argv_empty 9y agoLike GP, I often wonder what untyped languages offer over typed languages for prototyping, and this "soooo much annotation!" thing just isn't a satisfying answer anymore. "Typed" does not mean "as verbose as C#/Java."
- dozzie 9y agoFirst, this annoyance does not come from static typing, it comes from C#'s type system. There are statically typed languages where you just construct the value and assign it to a variable, and compiler infers variable's type for you (e.g. OCaml). Then, typing the class name is a trivial matter. My editor offers me a generic text completion command, so I don't type full "GameObject", I just type "Ga" and hit ^P. Maybe you should try using a good text editor?
- sqeaky 9y agoHave an upvote for being perfectly reasonable and attempting to provide examples and reason, even if I disagree with them. Rather than deflect away from C#, I will take the unpopular stance of defending verbosity. Does typing that really represent a large waste of time? Do you spend more time physically typing than doing anything else while coding? I spend most my time thinking or reading old code. I might type that once and read it 100 times and pass the debugger over it 6 or 7 times and adjust the line a similar amount in the lifespan of that of the code. For reading it is entirely clear and leaves little ambiguity about what kinds of operations are allowed on GameObject (presuming I know something about the GameObject class and the Entity Component System in place). I know its location and its rotation and I know that those are unlikely to be the source of bugs. I might need to reference `MyGameObject` to get the specifics of the behavior, but if I am troubleshooting location or rotation errors, I know what code I am not looking at. If I am troubleshooting any other behavior I again know about whole regions of code I don't need to look at. It can be hard to internalize all that a type system buys for you because none of it is immediate, it is more about all the time you don't spend doing unproductive things. I find that in more dynamically typed languages I spend two the three times as much time debugging than in static languages.
- naasking 9y ago> It's not so great when I'm trying something new and am still trying to work out if what I want to do is even possible, since I find myself trying to identify the right type to use in a given situation rather than proving that I'm even able to do it. Finding the right type is solving most of the problem. If you can find the right type, you can solve the problem. If you're having trouble finding the right type, then you don't yet understand the problem well enough, and modelling what you do know with types quickly points out what parts of the problem you haven't fully understood, without having to run broken, half-specified programs that cover only part of the problem space. What makes you think being able to run such half-specified programs for part of the problem will actually help with answering this question?
- Veedrac 9y ago> If you can find the right type, you can solve the problem. Do you actually believe this?
- jerf 9y agoWhat's the most advanced type system you've used? It's quite difficult to explain how much work a very strong type system can do for you if you're used to something like C as your definition of "static typing". I mean this comment comment completely straight and polite, and I'm trying to help people answer your very reasonable question by asking you for some details that will help calibrate the answer.
- Veedrac 9y agoTechnically that would be something like Haskell's, but I only have surface-level fluency. More to the point would be the most complex stuff I've had reason to do with a type system, which caps at around this generic state machine: https://play.rust-lang.org/?gist=3fdb20c34d589a2576c6bb137b9fd359&version=stable&backtrace=0 https://play.rust-lang.org/?gist=3fdb20c34d589a2576c6bb137b9... (TL;DR: A type that encodes a state machine (and is generic over the implementation) that allows you to guarantee reaching a terminating state.) In practice I rather my types looking much plainer, though: https://github.com/llogiq/bytecount/blob/master/src/lib.rs https://github.com/llogiq/bytecount/blob/master/src/lib.rs
- mixedCase 9y agoWith a good type system, instead of writing algorithms first you would write data structures that convey the ideas behind the software's intent clearly. Then you start writing the algorithms that manipulate these data structures. If what you're trying to do is viable, then you'll be able to express it in the domain model.
- sk5t 9y agoYes! I've found it quite effective to start new problems with some (mostly composition-based) types as a means of jotting down the core inputs and outputs, then work out towards the edges in both directions with deserializers/readers/parsers in one direction, and repositories and work-doing algorithms in the other direction. A little dependency injection to wire the pieces together in complex systems and you're in business.
- jmull 9y agoI usually start design with a domain model, whatever the type system I'll be working with. (Just pointing out you can go this route regardless of your type system.)
- marcosdumay 9y agoPersonally, I did never feel that way. Either types come out mechanically and just mean some more typing slowing me down because they don't say anything interesting, or creating the types is exactly "proving that I'm even able to do it". I tried, but I can't recall any single time when thinking about types distracted me from thinking about the problem. Moreover, writing down the types by creating stub functions is a great method of designing.
- JamesBarney 9y agoWhen I'm still prototyping I usually pick the part of the project I am the most uncertain about, then write a big function with lots of anonymous types. Once I feel more familiar with it I refactor into types. But types can also be really useful when you are in the process of learning your domain. If I'm using javascript and I realize I could better represent my code if I did some refactorings I usually don't touch it because I fear breaking something. On the other hand if I'm using a statically typed language I feel free to refactor to my hearts content with the knowledge that the chance I break something is far smaller.