316 karma · joined January 5, 2019
F#'s Type Providers can do that too.
https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/typ...
If yes, than it's a really bad bad thing and I hope they change it.
CLAs that permit relicensing for a project that already uses permissive license is fine and fair. But doing that on a project with a copyleft license is a bad taste. It would enable Grafana Labs to give Grafana to a party X which can then give it to party Y, where X isn't required to give all the necessary freedoms to Y.
Thankfully it won't. Scala 3 deconstructs implicits and discourages (or outright discards) the bad parts: http://dotty.epfl.ch/docs/reference/contextual/motivation.ht...
"Implicits" are useful for the Type class pattern and is available in Scala 3 with an improved syntax.
"Implicits" for implicit conversions is an ugly hack that should be avoided as much as possible and Scala 3 restricts it.
"Implicits" for extension methods is a clever hack, and Scala 3 provides a dedicated syntax for defining extension methods.
Of course it does. And since Scala 3, it does suggest to you the imports you need for implicits. And IntelliJ does recommend imports even for Scala 2.
Regarding cats, the codebase has been restructured, so that you won't need the implicit imports (or not as much at least): https://meta.plasm.us/posts/2019/09/30/implicit-scope-and-ca... The trick there is that the Type class instances were moved to appropriate companion objects which are searched by the compiler by default and thus the used doesn't need to do any manual imports.
Kinda yes, kinda no. There's a whole interesting story to it:
Although I miss type providers, enforced lack of cycles and other nice things, like syntax:
https://contributors.scala-lang.org/t/scala-3-very-impressiv...
That is alarmingly false. Do you have a source that McNealy indeed has said that? I couldn't find anything by googling.
That means, that if I have a polymorphic (generic) class `MyClassA<T>`, the compiler (regardless if it is JIT in the runtime as in C#, or AOT as in Rust) monomorphises (reifies) `MyClassA` for each instantiation of `T`. So `MyClassA<MyClassB>` and `MyClassA<MyClassC>` are distinct classes.
For this reason, co-/contra-variance in C# works only for interfaces. Type parameters in classes are invariant. `MyClassA<MyClassB>` and `MyClassA<MyClassC>` are distinct classes, neither sub-/super-class of the other, even if `MyClassB` were a subclass of `MyClassC`.
On the other hand, C#, F# or Rust monomorphise (have reified generics).
F# has been an unwanted child of Microsoft, it actually adopted the language from Microsoft Research. As a language, F# is _very_ good (although not as good as the original OCaml, whose features had to be cut to be able to run on CLR). It's just not first-class citizen, so not everything may work with F#. And F#'s own development and features are blocked on CLR -- instead of F# charting its own path, each feature first has to be available for C#/CLR and only then will F# developers implement it (higher-kinded types are just one example).
But it's still much more pleasant "syntactic sugar to write the CIL bytecode" than C# can ever be.
> even Scala is dead
I beg to differ! Thankfully, Scala is very much not dead. Scala 3 is around the corner, with many more features and, even more importantly, several simplifications. And the community is also much larger compared to F# (or any other ML language, like Haskell). Innovation also takes place in the realm of libraries, like ZIO for example.
Algorithms are _literally_ mathematical objects. C.f. Church-Turing thesis.
> And if it were simply math, then there would be no way to work around those patents, which plenty of open source codecs have done in various directions.
Show me an H.264 codec that works around the patents in the MPEG LA pool. Also software patents are orthogonal to the question of "open source" (which is about copyright). That there is very often no way to work around the patents in an otherwise independent implementation is precisely the problem with Software patents.
> Unfortunately, most open source codecs are not as good at compression, mostly since the patented ones have a massively bigger pool of engineering behind them from dozens of companies banding together their work to develop best of breed solutions.
Show me the numbers. Because the numbers I know (for example the chart in the blogpost itself) show that x265 is the best codec (or encoder, if it's not a decoder too) for H.265, it self being "open source", better than proprietary alternatives.
> And eventually the patents expire, and the world gets these codecs free to use.
Even after patents expire, copyright expires in 90 years.
There are libraries like ZIO, Cats Effect or Monix. Give them a try! Some people might even say that for example ZIO is even better than Haskell's IO.
One of the things I liked best about F#.
There are ideas/proposals how to fix that: https://www.youtube.com/watch?v=ARYP83yNAWk
https://news.ycombinator.com/item?id=25305574
I hope you will find it helpful.
Since you've brought out Haskell's IO and Scala libraries' IOs (Monix, ZIO, Cats Effect), or F#'s Async, I think it's worthwhile to point out how they're different from the async-await approach that's in C#/Kotlin/Rust/etc.
They both require "special" handling -- in C# it's the `async`/`await` syntax, in Scala it's the flatMap function or for-comprehension -- there they are similar. But their meaning is different. IO/Task in Scala doesn't represent a possibly started and under-way computation; it represents a "dead" program, yet to be started, a mere value. And it has all the advantages that mere values have, like refactoring (extract variable, ...) or restarting in case or failure and so on. Pass it into a method, return it from a method, store it in a data structure/collection, create `IO[IO[X]]`, whatever you want, just like you would with `Option[X]` or `List[X]`. In Scala, you have to differentiate between `A => B` and `A => IO[B]`, because `B` and `IO[B]` are different, but both are still values. Your program then ends up being this one big IO/Task value, which is then executed "at the end of the world". These pictures illustrate it quite well:
https://twitter.com/impurepics/status/1182946618280153094
https://twitter.com/impurepics/status/1180064851219144704
On the other hand, async-await has none of the benefits, only downsides. You get functions of two colors, but no benefit in return. It's justifiable in Rust, because Rust aims for zero-cost abstractions. But for Kotlin/C#, it's a sad choice.
The Loom approach for Java is a reasonable one. No async-await shenanigans, no funny FP/Haskell/IO business. You just use threads for concurrency as God intended them and you can have gazillions of them, because they are M:N. And I respect that, even though I'm partial to IO/Task for the reasons outlined above.
Is has already been mentioned a couple of time in this thread, but it deserves a more prominent mention, because IMHO it's a really interesting project.
The author(s) analysed git UX shortcomings and tried to learn from them. For example, Gitless aims to align well its concepts with user's intentions. There have been written research papers (and a talk is available online) about their methodology and Gitless design:
Ban recursion and unbounded loops. Proclaim the language is "Turing incomplete" and that all programs terminate.
Declare that Turing incomplete programs are simpler. Have non-technical people conflate terminate quickly with terminate eventually.
Realise lacking recursion makes things incredibly clunky to express, turning simple problems into brain teasers.
Add recursion.
Realise that the everything is better.
https://neilmitchell.blogspot.com/2020/11/turing-incomplete-...There are now more people who care about these things and more quality Free software available than ever before in human history! It's just that the complacent open-source idea, as well as proprietary software (biggest offenders are locked smartphones, etc), have spread even faster :(
I don't think the movement has weak foundations nor that it is politically naive. In my eyes it goes directly to the problem it cares about, which is human freedom in the context of using a computer. It doesn't oppose commerce, but it is aware of the current socio-political order's (i.e. capitalism's) tendency to turn anything into a sellable commodity.
The point of Copyleft (and the Free software movement in general) is to ensure that the user of a computer (and the software in it), a human being, is free -- meaning she can do with it what she pleases. Use if for whatever, study what it does, change it, share the original or modified version -- those are the four freedoms https://www.gnu.org/philosophy/free-sw.en.html . Humans can't be free, if they're not in control of the computers/software that they use.
The Free software community considers it unethical, if a cellphone owner or an automobile owner can't do with her device (including the software it runs) what she wants, even though she bought it with her hard earned money.
A talk introducing the issues with git and how gitless improves upon them https://www.youtube.com/watch?v=31XZYMjg93o
Conversely, Scala has the expectation of (partial) type erasure as is done on JVM, and that's probably why the .NET port didn't get very far.
How could you have not mentioned OCaml? The original Rust compiler was implemented in it. By this, Rust has a very clear (OCa)ML heritage.
It's meaningless to argue, whether Rust got ADTs from Haskell or OCaml, because the author (Graydon Hoare) had been clearly familiar with both and both got ADTs from ML, which is much older than either of them.
On the other hand, traits are a different story, those just Type classes with a different name, and that is a Haskell thing.