-
-
Notifications
You must be signed in to change notification settings - Fork 624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a rule about best / bad practices for implicits and context bounds #33
Comments
Implicits should be used with care, I agree, but the availability of context bounds is what defines Scala as a language in my opinion and one of those things that made me switch to it. To be clear, using context bounds is when you do this: def something[A : B](a: A) = ???
// or ...
def something[A](a: A)(implicit ev: B[A]) = ??? This opens up the possibility of using type classes in Scala, a form of adhoc polymorphism that's solved at compile-time. And you have examples from the standard library of such usage: def sum[A : Numeric](list: Set[A]): A = {
val ev = implicitly[Numeric[A]]
list.foldLeft(ev.zero)((sum, e) => ev.plus(sum,e))
} Such a function works with Going forward, this is what enables libraries like Cats or Shapeless or Spire to exist. Nowadays you even have libraries like simulacrum to help with the boilerplate. It's also highlighting why a statically typed FP language really needs higher kinds. This is why for example Java, C#, F#, Swift, Ceylon and Kotlin are really bad at FP (and I'm not even mentioning Go, because that goes without saying). I mean, if I'd add a rule, I'd encourage the usage of context bounds. But then in Scala this is a topic that tends to polarize, probably because Scala developers come with diverse backgrounds and opinions. I do think a rule about preferring context bounds to view bounds would be useful. Implicit conversions are problematic and usually you can choose a safer alternative by means of context bounds. I did such a mistake myself in my library. So we've got the trait Observable[+T] {
def flatMap[U](f: T => Observable[U]): Observable[U]
} But a Scala standard object Observable {
implicit def futureAsObservable[T](future: Future[T])
(implicit s: Scheduler): Observable[T] = ???
} But then we've got problems:
But such a problem can be solved by introducing a type-class (note this does use higher kinds), like: trait CanObserve[O[_]] {
def convertToObservable[T](o: O[T]): Observable[T]
}
object CanObserve {
// Automatically visible, because the definition is in the companion object
implicit def future(implicit s: Scheduler): CanObserve[Future] = ???
implicit def iterable(implicit s: Scheduler): CanObserve[Iterable] = ???
} And then we can have this and it will just work: trait Observable[+T] {
def flatMap[U, O[_] : CanObserve](f: T => O[U]): Observable[U]
} |
Implicits are a core feature of Scala, and using them reasonably is a good practice. @alexandru gives some good examples of this. Please close this non-issue. |
Hi guys, thanks for the input, appreciate it. I did not mean these features should be removed from the language. What I meant was that being somewhat more advanced concepts they are subject to misuse, and I thought it would be nice to give some guidelines as to how one should properly use them so that he gets the benefits without falling into the pitfalls. For instance, context bounds that are propagated along a dependency chain until they are present in types for which having a particular implicit makes no sense, might not be a best practice IMHO. I believe my example would be best discussed over an example, which I hope I'll soon have time to put here. Nonetheless, I'd appreciate if could take a minute to see if you can see the point I was trying to make. I'll also revise the headline accordingly. -Stas |
Ah ok, I misunderstood the heading then, sorry about that. Sure there should be some guidelines. |
@staslev I think you're right in that we do need guidelines for implicits and this ticket was needed.
On propagating an implicit, that example would be great. Whenever you've got the time :-) PS: you keep using "practise" as a noun. I'm not a native English speaker, but I think that's the verb form (to practise) and the noun should probably be "practice". Or is this an American vs British thing? :-) |
@alexandru You are right, my bad. |
No, not at all. Take my "advice", an easy way to remember is (as they sound different)....
|
I feel like there should definitely be some guidelines about this, as it can be (and is) very easily abused.
I've been playing around with code to help demonstrate some ideas, hopefully I can share the insights in the not so far future. Also, if you guys have any input on this, please do share.
-Stas
The text was updated successfully, but these errors were encountered: