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
I can tell you what the error is in 99% of the cases (unless you're using shapeless)
there's some method that needs an explicit type ascription like foo[F] somewhere
you can find it by finding a method that has a type parameter that then appears only in an implicit parameter list
for example def write[F[_]](a: String)(implicit F: Thing[F])
Nick Telford
@nicktelford
ahh, so it's usually caused by a type inference issue rather than a recursive implicit search?
@SystemFw what if that method itself is implicit :D
Rob Norris
@tpolecat
What is the exact message you're getting? It should tell you what the compiler is looking for. If it's not what you're expecting then you can often fix it with an explicit type argument at the point of failure.
If it is looking for what you're expecting then you may not have an instance in scope, but there may be something the compiler thinks will lead to an instance and it's off on a goose chase that will never end.
Fabio Labella
@SystemFw
@nicktelford depends on the context. If you're using shapeless (or code in shapeless style like inductive instances), then it's recursive search yeah (hence my initial caveat). In "normal" cats user code is the case I mentioned and that Rob has explained more often than not
Nick Telford
@nicktelford

so I have the following:

implicit def derived[A[_[_]], F[_], G[_]](implicit af: A[F],
                                          f: F ~> G,
                                          fk: FunctorK[A]): A[G] = fk.mapK(af)(f)

TopicsAlgebra[IO]

(I also have a bunch of impliclty calls to verify that the required implicits are in scope)

the error I'm getting is:

[error]      diverging implicit expansion for type TopicsAlgebra[cats.effect.IO]
[error]      starting with method derived
[error]      L87:          TopicsAlgebra[IO]

so as you can see, I can't add type ascriptions to the method call-site, because it's an implicit method

Rob Norris
@tpolecat
General observation, ~> isn't a typeclass so you don't normally want them to be implicit.
Also, how implicit is it? implicit af
sorry
Can you call derived explicitly with explicit type arguments and get the result you expect? It's possible those type parameters can't be inferred.
Nick Telford
@nicktelford
That works:
derived[ConnectionIO, IO](implicitly[TopicsAlgebra[ConnectionIO]], fk, TopicsAlgebra.functorK)
Fabio Labella
@SystemFw
a ConnectionIO ~> IO used like that seems scary :)
Nick Telford
@nicktelford
@SystemFw @tpolecat perhaps I'm asking the wrong question :) what's the idiomatic way to work with doobie within an http4s program?
Fabio Labella
@SystemFw
you shouldn't need any of that
Nick Telford
@nicktelford
I have my DAO algebras in ConnectionIO, and my HttpRoutes in IO - I've been trying to avoid passing the Transactor through to my http layer, in an effort to keep the http layer independent of ConnectionIO
Fabio Labella
@SystemFw
I would probably need more context about your code to give you a more precise answer, but generally I'd be explicit about when ConnectionIO becomes IO, given that that's where transaction boundaries are inserted
Nick Telford
@nicktelford
are there any non-trivial example repos you could point me to?
Rob Norris
@tpolecat
I think in general what I would do is have a service layer like trait Service[F[_]] { def getUser(id: int): F[User] } and then implement it, given a Transactor[F]. The implementation would be aware of doobie but outer layers wouldn't be.
Then it fits in with http4s's tagless design.
Fabio Labella
@SystemFw
yeah, i was about to say the same
Ryan Zeigler
@rzeigler
would it be possible to implement a Service[ConnectionIO] and then mapK it with something derived from the transactor as well?
Nick Telford
@nicktelford
so that's kinda what I'm doing: TopicsAlgebra is an example of my "service layer"
Andi Miller
@andimiller
@rzeigler you need an imapK and I don't think I'd recommend people code like that, I did try writing one - https://github.com/andimiller/http4s-doobie-poc/blob/master/src/main/scala/net/andimiller/http4sdoobiepoc/HelloWorldServer.scala#L15-L24
Rob Norris
@tpolecat
It makes total sense to have a layer in terms of ConnectionIO. This gives you the sub-transaction pieces you can compose.
Andi Miller
@andimiller
and it does technically work
Nick Telford
@nicktelford
my issue is that, once I have a Service[ConnectionIO], I need some way to lift that to IO so that http4s can work with it
which is what I was trying to do - but I feel like I was doing it in a really roundabout way!
Rob Norris
@tpolecat
But composing them and then translating to your target monad F (given a Transactor[F]) isn't just a transparent translation. It defines transaction boundaries.
Nick Telford
@nicktelford
that's ok in this case, as each method on my Service layer is expected to be a transaction
Rob Norris
@tpolecat
So I recommend distinct layers because they have distinct semantics and in the general case won't line up 1:1
Ok.
Nick Telford
@nicktelford
though I am curious about the general case
Rob Norris
@tpolecat
Well in that case yeah you can mapK with transact and get a new service thing in IO or whatever.
But in the general case that's too constrained. If you ever want to do two things in a transaction you're out of luck.
Ryan Zeigler
@rzeigler
That allows some of your services to depend on others while still allowing tranasction blocks correct?
ergo, ServiceB[ConnectionIO](sa: ServiceA[ConnectionIO])
Luka Jacobowitz
@LukaJCB
Folks, care to comment on this issue? :) non/kind-projector#84
Nick Telford
@nicktelford
so the reason for my derived implicit def from above is that I have a bunch of different algebras, and I didn't want to have to write Alg[ConnectionIO].mapK(xa.trans) 10 times - I was simply trying to have it auto-derive it - but perhaps that's just not a good idea
I must admit, while I've been learning the pure-FP side of Scala, the most difficult thing by far is idioms around program structure, mostly because there seems to be very little literature around it
Rob Norris
@tpolecat
Yeah Someoneā„¢ needs to give a talk on how to write programs using cats.
Nick Telford
@nicktelford
I would watch the hell out of that! :D
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