Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Tim McIver
@tmciver
Yup. OK, I see.
Fabio Labella
@SystemFw
trait Printable[A] {
  def format(input: A): String 
  def print(input: A) : Unit
}
do you also know why they do it?
(if not, I can explain, and I can tell you a more common alternative)
Tim McIver
@tmciver
I think because those methods are automatically imported when the trait is imported . . . ?
Fabio Labella
@SystemFw
the trait is not imported anywhere
Tim McIver
@tmciver
The book probably said but now I forget! :|
Fabio Labella
@SystemFw
ok, so imagine that the syntax bit doesn't exist for a second
say you have
def foo[A](a: A)(implicit p: Printable[A]): String = p.print(a)
makes sense so far?
Tim McIver
@tmciver
Yes
Fabio Labella
@SystemFw
this works, but generally you want to use context bounds because they are less noisy
they are just syntactic sugar so exactly equivalent
def foo[A: Printable](a: A): String = problem.print(a)
your evidence is not named so you can't really use the context bound
do you see?
Tim McIver
@tmciver
By "evidence" you mean the A: Printable part?
Fabio Labella
@SystemFw
you don't know how the Printable evidence is called (the compiler generates a fresh name when you use a context bound)
by "evidence" I mean the p in implicit p: Printable[A]
Tim McIver
@tmciver
OK, I see.
Fabio Labella
@SystemFw
the : Printable in A: Printable is called a context bound
Tim McIver
@tmciver
:thumbsup:
Fabio Labella
@SystemFw
and it's desugared into implicit $mangledCrazyName: Printable[P]
Tim McIver
@tmciver
And you have problem there because we don't have a name for the evidence?
Fabio Labella
@SystemFw
yeah
Tim McIver
@tmciver
Ah, I didn't know that desugaring.
Fabio Labella
@SystemFw
unless you revert to using an explicit implicit myName, which is noisy
however, if you do
object Printable {
  def format[A](input: A)(implicit p: Printable[A]): String =
    p.format(input)

  def print[A](input: A)(implicit p: Printable[A]): Unit =
    println(format(input))
}
you can now do
def foo[A: Printable](a: A): String = Printable.print(a)
Do you see this? (before we go to the next part)
Tim McIver
@tmciver
Yes
Fabio Labella
@SystemFw
so, this works
but it's a bit boilerplate-y, we had to replicate all the methods in the Printable trait also in the Printable object
so you often see a different thing instead
object Printable {
   // summoner
   def apply[A](implicit ev: Printable[A]): Printable[A] = ev
}
that single apply replaces print and format
it just grabs the printable from implicit scope and gives it to you
why?
cause you can do this now
def foo[A: Printable](a: A): String = Printable[A].format(a)

def bar[A: Printable](a: A): Unit = Printable[A].print(a)
without needing to replicate both print and format into the Printable object
does that make sense?
Tim McIver
@tmciver
Because Printable[A] calls the apply method!
Fabio Labella
@SystemFw
yes
Tim McIver
@tmciver
Yes, I've seen this before but now it makes sense!
Fabio Labella
@SystemFw
right, there's two additional pieces of info that should complete the puzzle
first, scala stdlib already gives you the implicitly method that behaves the same as apply
so you could do implicitly[Printable[A]].format instead
def implicitly[A](implicit ev: A): A