Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Rob Norris
@tpolecat
This is a small program that uses a pattern that's working well for me. tl;dr tagless interfaces are always traits and F is always unconstrained. Implementations are anonymous, often on companions, and are constrained as necessary. https://github.com/tpolecat/mosaic-server
Nick Telford
@nicktelford
@tpolecat thanks
Rob Norris
@tpolecat
I'm doing the same thing with https://github.com/tpolecat/skunk and it kind of writes itself. Seems like a good pattern.
You might also look at @LukaJCB's talk from SBTB
Fabio Labella
@SystemFw

, the most difficult thing by far is idioms around program structure

tbh that's the most difficult thing in general, because imho there is no one-size fits all approach, in any tech (and the tech that force one on you like Elm end up very limiting). I do agree we need to do a better job popularising things that do work, but it's a bit hard to discuss application structure in any way other than working together on it

fwiw, I use roughly the same pattern @tpolecat mentions
Nick Telford
@nicktelford
Rob Norris
@tpolecat
Yes, that's the one.
Nick Telford
@nicktelford
Thank you both, you've given me a fair bit to think about. I think one of the key differences is that you're assembling your algebra explicitly, rather than implicitly, which doesn't put you at the mercy of Scala's implicit search and type inference quirks. That seems sensible!
Jakub Kozłowski
@kubukoz
@nicktelford also check out splain
Fabio Labella
@SystemFw

@nicktelford

I think one of the key differences is that you're assembling your algebra explicitly, rather than implicitly,

What I do is passing algebras implicitly, like F[_]: MyThing, but having explicit constructors in the companion object, and then using implicit call sites, basically

constructor.flatMap { implicit alg =>
  thingThatWantsImplicitAlg
}
this gives me low boilerplate but no implicit weirdness
especially because in current scala if you nest two of those with the same type you get a compile error (which is what you want)
the only thing you need to remember is to make things implicit as close as possible to their call site, which isn't that big of a rule in terms of practical pain (almost none)
Jakub Kozłowski
@kubukoz
generally implicit auto-derivation of algebras becomes really painful for testing as soon as you stub anything
Rob Norris
@tpolecat
There's some subtlety to this that probably deserves a blog post.
Jakub Kozłowski
@kubukoz
Someone™ should write one
Luka Jacobowitz
@LukaJCB
I gotta say I'm a huge fan of
Someone™ , they seem to be doing a ton of work
Long Cao
@longcao
Jakub Kozłowski
@kubukoz
I was about to say something about being ashamed of giving Someone so much to work on
Ryan Zeigler
@rzeigler
Well, the rewards of a job well done and all that
Ryan Zeigler
@rzeigler
so, simpler question, what is the proper name of the >> syntax?
like, *> is to productR
Rob Norris
@tpolecat
Not really simpler, the original names were *> and >>.
People kept asking us to make up a non-symbolic name so we invented productR
Oleg Pyzhcov
@oleg-py
Which is even worse :D
Rob Norris
@tpolecat
:-)
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