Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 06:05
    mergify[bot] labeled #6514
  • 06:04
    danicheg opened #6514
  • Jul 05 20:56

    github-actions[bot] on gh-pages

    deploy: 8a97d89e13db1c752ff1b47… (compare)

  • Jul 05 20:52

    armanbilge on series

    (compare)

  • Jul 05 20:52

    armanbilge on 0.23

    Update jawn-parser to 1.4.0 in … Merge pull request #6513 from h… (compare)

  • Jul 05 20:52
    armanbilge closed #6513
  • Jul 05 20:29
    mergify[bot] labeled #6513
  • Jul 05 20:29
    mergify[bot] labeled #6513
  • Jul 05 20:28
    http4s-steward[bot] opened #6513
  • Jul 05 20:28

    http4s-steward[bot] on series

    Update jawn-parser to 1.4.0 in … (compare)

  • Jul 05 19:23

    github-actions[bot] on gh-pages

    deploy: bc2f3d5e075ad289c68ac58… (compare)

  • Jul 05 19:21
    rossabaker opened #280
  • Jul 05 19:21

    rossabaker on 0.23.13

    Merge branch '0.22' into 0.23 http4s-0.23.13 (compare)

  • Jul 05 19:20

    armanbilge on 1.0.0-M34-1

    (compare)

  • Jul 05 19:19

    rossabaker on main

    Release v1.0.0-M34 Merge pull request #6512 from h… (compare)

  • Jul 05 19:19
    rossabaker closed #6512
  • Jul 05 18:54
    mergify[bot] labeled #6512
  • Jul 05 18:54

    rossabaker on 0.22

    http4s-0.22.14 Merge pull request #279 from ht… (compare)

  • Jul 05 18:54
    rossabaker closed #279
  • Jul 05 18:54
    rossabaker opened #6512
Fabio Labella
@SystemFw
you also want named arguments, or is withLog enough?
Ross A. Baker
@rossabaker
Because the Sync[F] is really in a parameter list after the log.
Uh... withLog would be sufficient for this use case.
Christopher Davenport
@ChristopherDavenport
def logMe[F[_]: Sync](s: String, logAction: Option[String => F[Unit]]): F[Unit] = {
    val log = logAction.getOrElse({s => Sync[F].delay(println(s))})
    log(s)
  }
Option variant
Ross A. Baker
@rossabaker
All of our other configs are inspectable before they're built, so I don't really like the laziness/optionality of it.
Fabio Labella
@SystemFw
you could build a bunch of different apis.
thing.withFoo(...).withBar(...)
thing { builder => builder(foo = myFoo, bar) }
Christopher Davenport
@ChristopherDavenport
def logMe[F[_]: Sync] = new logMePartiallyApplied[F]
private class logMePartiallyApplied[F[_]: Sync]{
    def apply(s: String, logAction: String => F[Unit] = {s => Sync[F].delay(println(s))}) = 
      logAction(s)
  }
Partially applied approach.
Ross A. Baker
@rossabaker
I'd like to be able to have a default argument that might fall through to an implementation of last resort, but Java doesn't let us define that for this type.
Fabio Labella
@SystemFw
right, ok
Christopher Davenport
@ChristopherDavenport
The intriguing part to me, is that due to the implicit nature, that partially applied variant is always equivalent.
Fabio Labella
@SystemFw
@ChristopherDavenport I'm not sure the partially applied works, you need a different name
as it stands, logMe[IO]("hello") will think that "hello" is Sync[F]
iirc I did make something similar work at some point, with apply, but it's more horrendous in implementation
like you need a magnet and so on
Christopher Davenport
@ChristopherDavenport
:scream: It gets worse.
Fabio Labella
@SystemFw
 found   : String("hello")
[error]  required: cats.effect.Sync[cats.effect.IO]
[error]   logMe[IO]("hello")
yep
Gavin Bisesi
@Daenyth
needs moar scala3 :p
Fabio Labella
@SystemFw
well, an easy fix for your code is renaming apply to of or build
(fun fact, when I originally suggested HttpRoutes.of I got the name while hacking on this exact problem)
(I mean the name HttpRoutes.of, not the idea, ofc)
Christopher Davenport
@ChristopherDavenport
Right, but what I really want is a rather simple syntactic change, and should be able to be automated somehow.
Fabio Labella
@SystemFw
heh, I'm not sure it's that simple, all things considered
Christopher Davenport
@ChristopherDavenport
Well noA => B => C => D to C => B => A => D should be doable.
Due to the implicit nature that’s the rearrangement, but it is baked into the language semantics that the transformation is not simple.
Fabio Labella
@SystemFw
there was a discussion a few days ago about supporting context bounds in higher-rank functions in scala 3, which was touching on a similar problem
I can see a few issues trying to implement mixing of implicits and not implicits lists. Not saying that is nonsensical or impossible, but it doesn't strike as particularly trivial, especially if you want to allow seamless explicit passing of implicit parameters as well
Fabio Labella
@SystemFw
@ChristopherDavenport if you want to indulge in evil
  def logMe[F[_]]: Magnet[F] = new Magnet[F]

  class Magnet[F[_]]
  object Magnet {
    implicit def conv[F[_]: Sync](m: Magnet[F]): LogMePartiallyApplied[F] =
      new LogMePartiallyApplied[F]

    class LogMePartiallyApplied[F[_]: Sync] {
      def apply(s: String, logAction: String => F[Unit] = { s =>
        Sync[F].delay(println(s))
      }) =
        logAction(s)
    }
  }

  def yolo = logMe[IO]("hello")
  // scala> yolo.unsafeRunSync
  // hello
tbh for a builder it's not that bad
changing names a bit
Christopher Davenport
@ChristopherDavenport
:100:
Luka Jacobowitz
@LukaJCB
How did you even come up with that :smile:
Fabio Labella
@SystemFw
I have this small library called eidos to encode IDs
mostly useless but I've learned a lot about bending scala to my will ;)
some of the stuff I have in a branch is truly crazy
like adding some sane error messages to that thing above
Christopher Davenport
@ChristopherDavenport
Sane error messaging, that seems unreasonable.
This is FP. 234sekjfasdf or it didn’t happen.
Fabio Labella
@SystemFw
with just that code if you do logMe("hello") you get "Magnet[F] does not get parameters"
let me see if I can remember how to fix that
(if it's fixable, lost track)
Christopher Davenport
@ChristopherDavenport
To be fair, logMe is definitely incorrect in the way scala does type identification in the first place.
Fabio Labella
@SystemFw
mm I think in the end I settled for just renaming apply to something else to get implicitNotFound-driven errors to work, can't quite remember anymore
I think the reason that makes it work in the correct scenario (it doesn't necessarily go through implicit search, but goes via the implicit conversion, thus avoiding the confusion between the input and the implicit parameter), it's also why implicitNotFound does not work (if it fails the implicit search you simply do not trigger the conversion)
Fabio Labella
@SystemFw
ah! I managed (just for the laughs though)
  def yolo = logMe[IO]("hello")
  // scala> yolo.unsafeRunSync
  // hello
  def well = logMe("hello")
Users/fabio/projects/playground/src/main/scala/Playground.scala:57: Specify `IO` there: `logMe[IO]("hello")`
[error]   def well = logMe("hello")
  def logMe[F[_]]: Magnet[F] = new Magnet[F]

  class Magnet[F[_]]
  trait LowPrio {
    @annotation.implicitNotFound("""Specify `IO` there: `logMe[IO]("hello")`""")
    trait Error
    class Catch[F[_]] {
      def apply(s: String, logAction: String => F[Unit] = ???)(implicit ev: Error) =
        ???
    }

    implicit def conv2[F[_]](m: Magnet[F]): Catch[F] =
      new Catch[F]
  }
  object Magnet extends LowPrio {
    implicit def conv[F[_]: Sync](m: Magnet[F]): LogMePartiallyApplied[F] =
      new LogMePartiallyApplied[F]

    class LogMePartiallyApplied[F[_]: Sync] {
      def apply(s: String, logAction: String => F[Unit] = { s =>
        Sync[F].delay(println(s))
      }) =
        logAction(s)
    }
  }
enjoy
Ross A. Baker
@rossabaker
So getting back to working around that error, I think the two questions are:
1) Do we want to be able to inspect the context on the builder?
2) What failure mode do we want if the default is bad and was not overridden?
Fabio Labella
@SystemFw
when you talk about 1), is the problem the fact that if you suspend the creation of SSLContext I can't see what's there without building one?
Ross A. Baker
@rossabaker
Yes.