Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Christopher Davenport
@ChristopherDavenport
Refer to *> and >>. Just easier. I use applicative discard and monadic discard when I’m discussing and people don’t know the symbol.
Ryan Zeigler
@rzeigler
I didn't know if there was a named version at all. *> documentation references produceR, but >> just says its equivalent to flatMap(_ =>
Ryan Zeigler
@rzeigler
for the record, I don't think productR is particularly confusing
maybe I'm weird
Rob Norris
@tpolecat
It's not confusing, just not well know. Everyone who has been doing this for a while will know *> but few would recognize productR.
Ryan Zeigler
@rzeigler
I guess that's fair. When I found that <*> was product, the reason productR is the name for *> made perfect sense
I guess thats more accurately what I meant
Fabio Labella
@SystemFw

There's some subtlety to this that probably deserves a blog post.

What's this ? I lost track

Rob Norris
@tpolecat
@SystemFw the thing where you don't want to introduce instances implicitly but it's probably ok to pass them along implicitly, as long as they're quantified in such a way that you can't really screw it up. For tagless algebras that aren't really typeclasses. ContextShift etc.
Tim McIver
@tmciver
Is this the right place to ask questions about the Scala with Cats book?
Rob Norris
@tpolecat
Sure! If it's specific to the book you may need to contact the authors but if it's about cats then yeah.
Fabio Labella
@SystemFw
@tpolecat ah yeah, sure. It's in my stack, which is very lazily evaluated ;)
Tim McIver
@tmciver

OK. My question is about implementing typeclasses. In the exercise for section 1.3 it shows how to implement syntax and has code like this:

object PrintableSyntax {
  implicit class PrintableOps[A](value: A) {
    def format(implicit p: Printable[A]): String =
      Printable.format(value)

    def print(implicit p: Printable[A]): Unit =
      Printable.print(value)
  }
}

In my implementation, which I did before looking at the answer, was to callformat/print on the implicit p. Is that wrong? Is there a reason to prefer the way above?

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)