Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Fabio Labella
@SystemFw
what does the above do? add functions to the companion object replicating each method in the typeclass?
(in the part that we don't see)
I would say that the way you did it is actually preferable
or at least more common
Tim McIver
@tmciver
It's to add extension methods to any type that has a Printable instance. The calls above are to methods in the Printable companion object:
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))
}
And my implementation was just:
object PrintableSyntax {
  implicit class PrintableOps[A](a: A) {
    def format(implicit printer: Printable[A]): String = printer.format(a)
    def print(implicit printer: Printable[A]): Unit = println(format)
  }
}
Fabio Labella
@SystemFw
right
that's what I thought
your way is more common
Tim McIver
@tmciver
OK, thanks.
Fabio Labella
@SystemFw
you can add methods to the object as well (I know some people that do it), but it's not really necessary (and adds a bit of boilerplate)
Tim McIver
@tmciver
@SystemFw can you expand on that? Do you mean they add the implicit class to the Printable companion object?
Fabio Labella
@SystemFw
no, I mean exactly what you pasted :)
your first code snippet
they are adding each method that's already present in the Printable typeclass to the printable companion object
do you see it?
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))
}
this bit
I assume this is the trait
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)