Plain Functional Programming by Martin Odersky [video]
youtube.com
youtube.com
The main example in the presentation compares Kleisli functors to impure imperative code, and then gradually transforms the imperative code to Kleisli equivalent using implicit function types without changing the body of the imperative code -- that was pretty cool.
I don't know if Scala 3 will be a game changer wrt to language adoption, but it's certainly going to deliver a lot of compelling new features/enhancements [1]
Based on the 6 week rolling release schedule a stable release should land presumably no later than this summer? That seems wildly optimistic but they released 0.4 last month...
Otherwise, refresh my memory, what was he warning about with implicits?
There's currently no way around definition site boilerplate (e.g. `implicit name: Type`); `implicit` keyword and providing a variable name are required. Implicit function types eliminate definition site boilerplate while providing function composition -- looks like a solid enhancement for FP in Scala.
What Odersky warns about is defining implicits on built-in types. Which IMO too often gets abused to hide poor design.
That PR [1] is (IMO thankfully) not merged yet (marked as on hold) and reminds me of the indentation-based syntax proposal - ambitious, far from consensus on it being 'a good thing' by actual users, full of workarounds or escape hatches being sought by everyone, almost unilateral and very little to suggest it's even solving the problem it claims to (and it's fuzzy on what that is, exactly)[2].
Matching Rust's rules on this seems like the source motivator for Odersky and that only leads me to recall a conversation I had with a friend on these two languages and about a dozen or so practical, dramatically boilerplate- or complexity-reducing solutions that library authors or I had coded up; these would be either outlawed or made into large, complex workarounds under this scheme (Rust rules).
Even in a codebase directly under my purview, we would have to duplicate implicits across modules (and keep them in sync), merge deliberately-separated modules and give up on some functionality altogether to support this proposal. These are mostly 'free' additional type safety constraints that we would just have to give up on.
I'm not against making changes to make implicits easier to 'see'[3] - I'd only say that an approach with the above problems that gets worked around anyway is not the solution.
[1]: https://github.com/lampepfl/dotty/pull/2060
[2]: Indeed even in this HN thread there are people criticising implicit parameters in a bunch of places (definitely not going away, IIRC Odersky likes them) - when people say 'they don't like implicits', between the various user demands they might well be removed in every variation.
[3]: Indeed in IntelliJ IDEA and Ensime, every implicit conversion is underlined at the point of use. In that thread, someone suggests making implicits importable only with a modifier.
As for the implicit aspect, we already have a way to pass implicit parameters to functions: fields. These have the advantage to actually be visible, injectable, and their semantics can't change just because you modified one import line.
Note that Dotty's implicit approach is similar in that respect, it doesn't prescribe anything in terms of mutability/immutability.
But we've already gone down the path of implicits, they are the #1 complaint about Scala, the #1 reason why the compiler is so slow and one of the main reasons why people say that Scala code can be very hard to reason about. I can't believe Odersky is doubling down on the implicit approach with Dotty. He just seems to be stuck in a language design corner and not willing to look at other ways to approach this problem.
It's programming language design myopia.
Personally most of the “wtf is going on here” comes from implicit conversions and usage of symbols (both of which have thankfully gone out of style for the most part)
The real question is: does the team you work with share your love of implicits?
Implicits are fun to use but they lead to code that's very hard to follow, so it's not uncommon to come across people who love them but these same people don't always realize the kind of code they are writing until way later.
But in general I haven't heard that many complaints outside of the few places where we use them for type level programming (Shapeless. Where most of the complaints are related to compile times). But the goal is usually to hide this behind some library or easy to understand type class instance and using implicits and shapeless to automatically derive the instances.
In general all the type class based stuff relies on implicits to be really useful and haven't really heard any complaints related to that pattern from anyone once they actually understand what type classes are and what they are used for.
Almost all the other use we have for implicits is automatically passing some context around in the app. This is things like RequestContext traveling down through the app and transmitting it to the next service in the chain. Basically only used so you don't have to be manually passing it around all the time. (another common example of this is passing ExecutionContext around. Or the ctx: Context in scalac that Martin mentions which appears 2600 times. If having it as implicit parameter 2600 times is pain think about having to manually fill it in)
Implicits conversions is something we try to say away from if possible (there are some valid use cases for it but be careful with it)
Can implicit fans explain to me how I am supposed to navigate to the correct overloaded method in Magnet pattern? Even IDE's like intellij Idea have no idea what to navigate to. If its so hard of an IDE to figure out, how are humans supposed to deal with this.
Implicits are great, and allow you to do some really amazing things, but you have to be careful not to abuse them or risk making your code take forever to compile and be impossible to debug.
I've got a theory that the type of people doing overly complex Java enterprise (see EJB 2.1) 15 years ago haven't vanished, they're just doing Scala now.
Basically it allows you to write
def f[T](fMagnet: FMagnet[T]): X => Y
f(t) { x =>
// ...
}
instead of def f[T](t: T)(implicit tc: TC[T]): X => Y
f(t).apply { x =>
// ...
}
so just about removing one ".apply"(see https://github.com/akka/akka-http/issues/100 where i copy pasted the code bits from)
But yeah first time I read up on the magnet pattern it was a wtf moment.
Scala neither has opaque syntax (see: many/most new languages borrowing its name:type format, smartly choosing [] over <> for type parameters, etc) nor does it have some weird execution model. Its a perfectly reasonable metric to use when talking about a normal/popular language, especially when people who don't even use the language complain about it being bloated and compare it to C++ which has a grammar twice the size of Scala. I really wish people would stop spreading FUD over these kinds of things :/
To be honest, this format was first introduced by ALGOL around 1960.
It does make more sense, though, compared to C's.
None of this talk seemed to have anything to do with actual software or the issues thereof.
But most of these complicated solutions (Kleisi) I imagine most viewers didn't even know about to begin with.