This really starts happening with a vengeance when you do increasingly lispy things, like creating dsls that move the language closer to your problem domain by writing programs that write programs.
Consider e.g. the way activerecord introspects the database schema to enrich your model declarations without further work from you.
Now there are ways to get similar effects in statically typed systems, but it's much more work, particularly if the dynamism comes from the execution environment (rather than compilation).
Also, regarding activerecord, it seems you're hinting at the benefits you get from composibility, is that correct?
https://docs.microsoft.com/en-us/dotnet/articles/fsharp/lang...
Regardless, I still think it's a moot point. I understand that static typing can be great for catching bugs sooner rather than later. But doing that takes time and work. Basically the thing that all static typing advocates neglect is that sometimes I just don't want to put that time and work in up front.
Most people would agree they'd want to put that work in before shipping their software to millions of people, but most code is only used by a few people a few times. The line between development and production is blurry. Most of the time, I would much rather run code that mostly works _now_ and has tons of bugs than have to put in more work. Even if it's not much more work, it's still not nothing. I own my computer and tell it what to do. But a compiler rejecting my code b/c there _might_ be an edge case that has an error is unacceptable. Which is why I would love static typing if you could simply turn it off. I know of some research in gradual typing, but I've never seen it in any mainstream languages.
Based on a quick web search, the equivalent of F#'s active patterns in Haskell appears to be view patterns...
https://ghc.haskell.org/trac/ghc/wiki/ViewPatterns
...and the closest I found for OCaml was polymorphic variants...
https://realworldocaml.org/v1/en/html/variants.html
>"I know of some research in gradual typing, but I've never seen it in any mainstream languages."
When you say gradual typing, do you mean optional type hinting like you can find in Python 3, or something else?
Thanks for the links. I didn't know about python's typing. It looks like a fairly recent addition.
Elm's to me embodies everything that drove me to Ruby over functional languages: Terseness in what to me is all the wrong places, coupled with too verbose typing.
> So what advantages am I missing?
The ones you have glossed over: More flexibility, and ability to be terse while readable. They matter more to many of us than you might think.
What finally sold me on Ruby was when I as an experiment rewrote a piece of queueing middleware we were using from C to Ruby and added significant number of features while cutting the number of lines to 10% of the original. Maybe I could achieve similar compact code with a statically typed language, but the likely candidates at the time at least were either extremely verbose or languages I considered absolutely unreadable (Haskell being top of my list of offenders - most of these languages have syntax that is clearly designed by people who are inspired by maths, unaware or not caring that this will push away most people).
I would love a "more static" Ruby, but I would not be willing to lose the terseness or expressiveness or readability to gain it. Maybe Crystal will get the balance right over time, though personally I believe you can get a lot more performance out of Ruby too without a lot of the sacrifices Crystal is making (but it will take a lot of work).
Elm can use type inference to work out types. The difference between this and dynamic languages is that it does it at compile time so you pay no runtime overhead.
Don't believe me? Take a look for yourself...
No, I'm speaking from having read a bunch of Elm code.
> Elm can use type inference to work out types. The difference between this and dynamic languages is that it does it at compile time so you pay no runtime overhead.
I know that. It does not change what I wrote as the outcome is that Elm code still includes more type annotations than I'm willing to deal with.
To get a better idea of how much type information you find unacceptable, do you have any problems with typed.rb code?
Most attempts to add static types to ruby code don't come with complementary tools to give us some of the advantages that would immediately gain developer support. In your editor, for example, code completion based on type annotations would be a huge plus, but I don't know of any tools that give me that in ruby (if they exist, I'm unaware). In most cases, your code will still run regardless, unless you use the separate tool to type-check, and are disciplined about its feedback. It's unlikely that all your team will _always_ run the type checker, and although you can have it configured to run the type checker on every save just like you'd do with tests, it's an inconvenience.
In terms of culture, I'm mainly thinking of Rails here, but I can think of more than a few ruby projects/libraries as well. Ruby is, simply put, a dynamic language. Even if you use typed.rb, you won't get much information about the libraries you'll be using. Code completion is mostly based off comments/documentation and only in some editors, and in many cases might not even be there. I also feel that many ruby developers simply don't like types, and that's the end of the story. I'm convinced that most don't see the advantages. For instance, in teams where we've added Rubocop to simply lint our codebases, I've noticed developers complain about warnings and errors that the linter reports, whenever the developer thinks they know better. I imagine the same happening with type annotations in ruby codebases. It would become a task that you run before committing or before a merge request (like tests, in some teams). When they're confronted with a bunch of errors, they'll go into flight mode: "but i've tested this manually and it works, why is this linter complaining, and why is my type checker complaining as well?". Needless to say, the type checker might have just flagged a _potential_ bug for a use case you might not have manually tested yet.
edit: I think tooling can help shift the developer culture aspect. Better tooling provides a better developer experience and in the end that's all we want. Flow and TypeScript are perfect examples (which I adore).
As for other Ruby projects, static typing would help with performance issues, why developers choose not to add types when hitting performance bottlenecks is not something I fully understand, perhaps it's just seen as normal to rely on C modules to increase performance. That said, Graal/Truffle does seem to offer hope that Ruby performance can be greatly improved.
Most prototypes fail to gain traction and are discarded well before they mature and maintenance costs start rising.
The only potential candidate I can think of is 'more flexibility'.
However, undefined behaviour is not a desirable trait when designing programs, and languages with static types have ways to provide polymorphic functions without unhandled behaviour (such as pattern matching on function arguments).
Some may argue that dynamic languages are more readable, but there are languages with static types that are both concise and readable (Elm being a good example), so I wouldn't class that as a benefit.
Some may argue that the speed of prototyping a solution is a benefit, but the time saved putting together a prototype is often negated by the time spent debugging as the prototype matures.
So what advantages am I missing? There must be something that makes dynamic languages popular. What reasons are there to use a dynamically-typed language over a statically-typed one?