5 ms·
C# does not in any way represent the best that static typing has to offer. Try F#, Haskell or OCaml seriously before discounting static typing. These functional
by willtim 9y ago
C# does not in any way represent the best that static typing has to offer. Try F#, Haskell or OCaml seriously before discounting static typing. These functional languages offer much better safety (e.g. no nulls, no casts, case exhaustiveness) and are as succinct as Python. They also generalise a lot of features that are ad-hoc in C# and Python (e.g. async-await is a library in F# and Haskell). For me, using Haskell is also like "designing a system in paper, friction free". In fact, I tend to write down the types and type check them, before I attempt to fill in any implementation.
Truth be told, I am not a Python fan. I am seeing it take over in my industry, because it's superficially 'easy' and it's popular. The lack of static typing only later becomes a big problem when large codebases start to appear with many contributors.
- kumarvvr 9y agoAny good resources on learning how to solve problems by leveraging strong type systems?
- willtim 9y agoThere's "Real World OCaml" (new) and "Real World Haskell" (a bit out of date). But my favourite introductory text, which is not free, is Graham Hutton's "Programming in Haskell".
- kumarvvr 9y agoThanks for the info. Just curious, what sort of problems are strongly typed languages most suited for? In the sense that which class of problems can be solved using them leading to elegant solutions.
- willtim 9y agoI use Haskell professionally in the area of quantitative finance in a large team with a multi-million line codebase. Everything is built upon domain specific libraries, sometimes many layers deep. And these libraries are constantly changing to keep pace with the business. Strong types tell us early when things are broken. Others are attempting to use Python for similar projects, but it isn't fun (we have some of their alumni). Haskell's effect typing also helps us. For example, for reproducible calculations, it is critical that no data is pulled-in via a backdoor (i.e. a side effect). Even reading and using the current system datetime is something we want to prevent. This can be expressed in the types using Haskell.
- kumarvvr 9y agoSo, highly reliable and completely transparent data processing. Awesome. Very interesting to know. I always assumed financial data processing, HFT, etc are done in java / C# or other mainstream languages. And yes, in such a situation, Python will not be an easy fit. Thanks a lot for sharing the info. Have been wanting to learn functional programming for a long time now. Specifically, I am planning to build computation systems based on Haskell, Scala, etc which sit behind a Message Queue server. Just to isolate the computation part from other mundane activities like HTTP request processing.
- tome 9y ago> what sort of problems are strongly typed languages most suited for I'm going to volunteer an answert to a slightly different question. "What sort of problems are strongly typed languages suited for?". They are suited for general purpose programming.
- yen223 9y agoThere's a famous quote by Linus Torvalds: "Bad programmers worry about the code. Good programmers worry about data structures and their relationships." Even when prototyping, I find that nailing down the data structures from the get-go makes subsequent code-writing much easier. A lot of times, the code kind of falls out naturally when you've figured out the data structures you're working with. Strongly-typed languages give you a nice way to define data structures.
- jejones3141 9y agoAnd Fred Brooks, from _The Mythical Man-Month_: "Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious."
- paganel 9y agoIt has been my experience that “data-structures” in real world situations and especially within code directly facing consumers varies a lot more compared to what any pre-implementation data design process can predict (I’d even say that the structure of a lousy data-input form on a god-forsaken website has the potential to change a lot more often compared to the intrinsic structure of the Linux kernel). Dynamic languages (like python or even php) are very good at tackling this real life situation, hence their popularity.
- Rapzid 9y agoThey are very good at letting you make the quick easy change while providing no helping hand in ensuring all your code is utilizing the data structure's new schema correctly They are "easy" in that sense which makes them popular with a subset if developers, while another subset loathes the terrible language services/tooling. Incidentally many dynamic languages seem to have attempted to bolt on some faux type system; python type annotations, phpdoc, jsdoc, type specs, etc, etc.
- baq 9y agoMypy, while somewhat bolted on and relegated to linter space, does an amazingly good job at bringing modern static typing to Python. Highly recommended to at least test drive it.
- e12e 9y agoI think the closest thing to "python with types" is probably Julia: https://julialang.org/ https://julialang.org/ I think the efforts of adding type/type hints to python are interesting - but there's a tension between "weee! Look at me ducktyping, metaprogramming all the prototypes!!"-design and leveraging types as part of your design. Haskell/f#/ml are great languages, but they feel very different from python (ml maybe less so,but afaik there are no full featured implementations with areasonable standard lib...). If Python is the starting point, I think there's probably four approaches that makes sense if python ends up being limited (in part due to lack of typing): move to a language like Julia, proto-type in python; re-employment in go, prototype in python; reimplement parts in cython and/or rust, add type hints on top of python. [ed: almost forgot, secret option number five: use restricted-python and the pypy framework to implement a language suited to the problem domain..]
- benji-york 9y agoEvery time I look at Julia, I like it a lot, right up to the point where I remember that indexing is 1-based and I loose the will to go on.
- newen 9y agoRolls eyes. 0 or 1 based indexing is one of the smallest thing to worry about in a programming language.
- e12e 9y agoI am in the odd situation that from habit collection[0] feels natural - but I actually think "first element" makes a lot more sense than "item at zero offset". Except maybe for things that are actually pointer+offset (which I think very rarely makes sense in high level languages/most ADTs). In fact, I think for situations where 0-based indexing makes sense, I'd prefer "memory_area+offset" rather than "pretend_collection_type[offset]". I also usually talk about "the first character" of a string, or first word of a sentence; not "word at zero offset from start". So yeah, I think Dijkstra's wrong on this one (or rather he has some very strong opinions on greater-/less-/-and-equal-to, and which are natural - for which I have little sympathy outside of abstract discrete math papers). http://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html http://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EW...
- mamcx 9y agoOr pascal/delphi. Python + pascal are by far the ones I enjoy the most. I do a lot of F# now, and I like it, except, is not a good pascal! i.e: The thing that bother my most of F# is that by default it not force to anotate types. One thing good about pascal is that is VERY EASY to figure out almost any line you read (without IDE help. Infurate me that F# know, but hide the knowledge to me!). With python is easy to infer the operations but not the data (ie: easy to read "I'm iterating" but not "and is a array of ints") I could anotate a lot on F#/Python but is not idiomatic. This mean, that a lot of times I'm lost with F# in the ways is with python, with the worse thing that the infered stuff get crazy hard. But, IMHO, python and pascal are in the TOP of truly well designed languages, where the sum of all the small things match well
- jbednar 9y agoAfter a decade of experience developing big systems in C and C++ followed by a decade of developing big systems in Python, my own experience is that static vs. dynamic typing isn't actually the issue that normally matters in a big system. Static typing is great for optimizing performance and for having efficient interaction with the underlying system libraries. So the closer your work is to the underlying machine and its types, the more important static typing is. But only a small part of any big system is usually like that, and static typing makes code harder to develop, harder to read, and needlessly limited in scope (overly specifying down to a machine type, when the actual algorithm may be far more general than that). Dynamic typing addresses those concerns, but it makes for a brittle system where each component makes a lot of undocumented assumptions about what might be passed in, with users of those components often just crossing their fingers about what the component might accept. Worse, dynamically typed systems eventually end up accruing pages and pages of hand-written documentation, assertions, and exceptions as people try to make them more well validated against user and external-programmer errors. All that well-intentioned "hardening" inevitably eliminates the readability benefit, except during initial development (when such checking is conveniently skipped). So neither static nor dynamic typing alone makes it easy to build big systems. What does make it easy to build big systems is semantic typing. I.e., the ability not just to declare a machine type, but to declare the actual assumptions made by any component about its inputs. In some low-level code those assumptions are about machine types (argument i must be an 8-bit integer, and s must be a string). But in other cases the assumptions are about what the argument represents (argument s is a string denoting a filename (not just any string), argument n is a number between 1 and 36.2 (regardless of machine type)). Any given component makes some assumptions about what it can handle, and if you can easily declare those assumptions and validate against them, then the component is easy to read, easy to understand, easy to use, safe against user errors, and easy to implement (as you don't have to write any code to handle conditions not allowed by the declarations). The beauty of Python is that semantic typing can be implemented very naturally within the language itself, which is crucial because it has to be extensible to handle any given domain's objects if it is to be of use. There are a variety of options, but my own package Param (https://ioam.github.io/param https://ioam.github.io/param) provides support for semantic typing, and if you look at some of the examples there you should be able to get a feeling for how you can have the best of all worlds in Python: freedom where you can handle it, constraints where you want them, and everyone being up front about what they are doing in a way that makes big teams able to work freely with whatever other people come up with.