Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    idir
    @iDumbo_gitlab
    si vous avez des idées je suis preneur
    etienne
    @crakjie
    @iDumbo_gitlab Alors personnellement je n'utilise jamais les constructeur directement donc je ne suis peut etre pas bien placer pour te repondre mais il me semble que scala supporte plusieurs constructeurs.
    Francois Armand
    @fanf
    @iDumbo_gitlab on ne pas ca en scala. Tu as un constructeur principal, les autres passent par lui. Tu peux faire ce que tu veux avec les apply de l'objet companion. Et en général, ca donne des choses beaucoup plus simple à débugguer par la suite (pas besoin de savoir si c'est le this ou le super en premier, ce genre de bétises)
    @ugobourdon
    @ubourdon
    @ahoy-jon J'ai regarder votre unboxing sur zio prelude c'était pas mal. J'ai fait quelques commentaires sur youtube
    1 reply
    @ugobourdon
    @ubourdon
    Yo: C'est normal que les messages d'erreurs de circe soit merdiques et ne me disent pas du tout ce qui manque dans mon code pour compléter un codec pour un objet donné ? Ou j'ai oublié un flag ou autre pour avoir ds message qui m'expliquent la vie comme avec play-json ?
    @ugobourdon
    @ubourdon
    Yo les amis. Est-ce que vous savez comment je peux faire un decoder CIRCE de type paramétré genre case class TOTO[A] parce que la doc me laisse un peu dans ma merde ...
    Julien Truffaut
    @julien-truffaut
    en general il faut que tu demande A d'avoir un decodeur
    implicit def totoDecoder[A: Decoder]: Decoder[Toto[A]]
    @ugobourdon
    @ubourdon
    Yep merci. En fait la feinte c'est que j'avais un encoder et un decoder de A dans le scope masi pas un codec. Et à la diff de play-json, il ne relie pas les deux.
    Jonathan Winandy
    @ahoy-jon

    Hey 👋, j'ai une question à la con, comment vous gérez les cas de la liste vide quand on attend une liste non vide ?

    Genre j'ai ça :

    
      def happyEyeballs[R, E, A](tasks: NonEmptyChunk[ZIO[R, E, A]], delay: Duration): ZIO[R with Clock, E, A] =
        tasks.reduceRight(raceWithHeadstart(_, _, delay))

    si je prends une List en entrée à la place, vous faites quoi sur le retour ?
    Des réponses :
    A. Yolo / orDie / assert, la liste vide est mise comme une erreur dans la sandbox et cela remonte
    B. Option[ZIO[R with Clock, E, A]]
    C. ZIO[R with Clock, Option[E], A] ou son copain le ZIO[R with Clock, E, Option[A]]
    D. la réponse D

    Francois Armand
    @fanf
    @ahoy-jon ca dépend la sémantique du cas liste vide. Je dirais sans plus d'info:
      def happyEyeballs[R, E, A](tasks: List[ZIO[R, E, A]], delay: Duration): ZIO[R with Clock, E, A] = tasks match {
        case Nil => ZIO.fail(Unsound("The list of task must be not null"))
        case h::tail => ...
    }
    Francois Armand
    @fanf
    evite Option[ZIO[...]], ca casse la cohérence des valeurs de retour, et c'est chiant à gérer. Si tu es dans ZIO, tu es dans ZIO, le test était avant (ie vaut mieux tester la liste, si non vide alors ton cas initial, sinon, ce que le business demande). Pareil pour ZIO[..., Option[E], ...]: ca n'a pas vraiment de sens. C'est juste une erreur comme une autre, tu fais un sous cas de E pour ca, et tu récupères ZIO[..., E1, ...]. Le dernier, ZIO[..., Option[A]] peut être pertinent, la sémantique étant "je m'attend à ce que je puisse ne pas avoir de résultat, ce sur le chemin nominal")
    Enfin: Yolo/orDie/...: pourquoi pas, si la sémantique est effectivement: "je ne veux pas modéliser cette erreure, et elle correspond à une limite de mon modèle, et donc si je tombe dans ce cas, je tue l'application"
    Jonathan Winandy
    @ahoy-jon
    merci d'avoir répondu ! Je pense que je commence à coincer sur cette histoire de list/NonEmptyList. Lors de la création des listes, on va favoriser que List(1, 2, 3) retourne une List[A] au lieu de NonEmptyList[A], de la même manière que l'on favorise Option(1) à retourner un Option[A] au lieu d'un Some[A] ..
    Julien Truffaut
    @julien-truffaut
    @fanf super explication
    Jonathan Winandy
    @ahoy-jon
    à la fin cela donnerait un truc comme ça si je garde la "cohérence" avec la lib standard ! :D
      def raceWithHeadstart[R, E, A](first:ZIO[R,E, A], second:ZIO[R, E, A], delay:Duration):ZIO[R with Clock, E, A] =
        Promise.make[Nothing, Unit].flatMap(isFailed => {
          val signalFailed: UIO[Unit] = isFailed.succeed({}).unit
          val waitOrAlreadyFailed: URIO[Clock, Unit] = isFailed.await.timeout(delay).unit
    
          first.tapError(_ => signalFailed).race(waitOrAlreadyFailed *> second)
        })
    
      def happyEyeballs[R, E, A](tasks: NonEmptyChunk[ZIO[R, E, A]], delay: Duration): ZIO[R with Clock, E, A] =
        tasks.reduceRight(raceWithHeadstart(_, _, delay))
    
      def happyEyeballs[R, E, A](tasks: Seq[ZIO[R, E, A]], delay: Duration): ZIO[R with Clock, E, A] = {
        val unsupported:ZIO[R with Clock, E, A] = ZIO.die(new UnsupportedOperationException("empty.happyEyeballs"))
        Chunk(tasks: _*).nonEmptyOrElse(unsupported)(tasks => happyEyeballs(tasks, delay))
      }
    En fait vous utilisez quoi pour les nonEmptyList de nos jours ?
    Julien Truffaut
    @julien-truffaut
    cats
    Jonathan Winandy
    @ahoy-jon
    Avec Zio pour les effets ?
    Julien Truffaut
    @julien-truffaut
    non je n'ai pas encore eu l'occasion d'utiliser ZIO serieusement
    j'ai plus d'experience avec cats-effect IO ou Monix
    Jonathan Winandy
    @ahoy-jon
    En fait j'ai attrapé une bonne allergie aux typeclasses, j'ai hâte de passer à Scala3 pour y revenir
    Francois Armand
    @fanf
    ::
    mais c'est un peu moche dans les API
    Jonathan Winandy
    @ahoy-jon
    Ho !
    Francois Armand
    @fanf
    mais au moins c'est standard
    je crois qu'on avait fait un alias à un moment, puis qu'on l'a enlevé pour je ne sais plus quelle raison (commentaire utile, du coup)
    Julien Truffaut
    @julien-truffaut
    c'est dommage que :: n'override pas les types de retours, par exemple, : est guarantie de retourner un autre ::
    Francois Armand
    @fanf
    en vrai, chez nous il y a peut de cas où on veut NEL. Souvent, c'est modélisable en paramPrincipal: A, autresParams: List[A] (ou dans l'état d'esprit). Et si on est en face d'api utilisateur (REST), il faut traiter List[A] de toute façon (avec du coup le cas erreur: ca ne peut pas être vide, et pour ca on a ajouté des combinateur .nonOptional("pourquoi donc") pour Option[A] et nonEmpty (pour list/etc))
    Jonathan Winandy
    @ahoy-jon
    le (A, List[A]) pour faire le nonEmpty ! Je trouve qu'en général l'ergonomie autour des cardinalités n'est vraiment pas top, on voit très bien comment représenter des 0:n, 0:1, 1:n, 1:1, ou même des 2:4 (entre 2 et 4 éléments), mais cela se finit avec beaucoup de boilerplate.
    Jonathan Winandy
    @ahoy-jon
    @julien-truffaut c'est exactement ça, j'ai eu le même problème lors du design à la base de NonEmptyChunk pour ZIO, tu finis par faire un type à part, qui n'est pas un sous type de Chunk pour réussir à faire des méthodes qui ont des types de retour plus précis , comme ++ ou autre.
    Julien Truffaut
    @julien-truffaut
    ah un moment j'etais tenté d'ecrire un SIP ou au moins un post sur le forum la dessus, mais je n'ai jamais eu le temps de le faire.
    je pense que ca aurait du sens que la libraririe standard est un NEL[+A] qui soit un alias de :: ou inversement et ou l'on redifini les types de retours quand c'est possible
    Jonathan Winandy
    @ahoy-jon
    Si tu veux prendre un "e-café" autour du sujet, je prends !
    Julien Truffaut
    @julien-truffaut
    :+1:
    Jonathan Winandy
    @ahoy-jon
    J'en profite, c'est n'est pas sur une de tes présentations qu'il y a une explication sur la différence entre le Range et le Codomain ?
    Julien Truffaut
    @julien-truffaut
    j'ai une presentation qui parle de la precision des fonctions en terme de domain, codomain et des tests
    Jonathan Winandy
    @ahoy-jon
    merci !!
    Francois Armand
    @fanf
    @ahoy-jon sur les cardinaux: c'est parce que c'est compliqué. C'est typiquement un "type dependent", et ca ne se modélise pas trop bien avec nos systèmes de types. Du coup, les réponses classiques sont soit de se tapper tous les cas (et bonjour l'ergonomie du truc au moindre refactoring, "ah zut en fait la borne sup ce n'est pas 17 mais 18"), soit tu passes en type + preuve manuelle (soit type inductif dependant comme Coq ou Lean, soit type + preuves embarquées comme isabelle/hol). Et là ca devient vraiment chiant en terme d'expérience utilisateur (note: il existe aussi le cas "code + pré/post-conditions, à la ADA, mais ca ne se voit pas dans les types)
    Jonathan Winandy
    @ahoy-jon
    Clairement pas faisable, néamoins pour 0:1, 1:1, 0:n et 1:n on aurait pu faire un effort
    Francois Armand
    @fanf
    il ne manque que 1:n
    Jonathan Winandy
    @ahoy-jon
    (Je regardais pour faire 2:4 en Scala, ... ouch !! cela pique !)
    Francois Armand
    @fanf
    2:4, le mieux c'est un ADT dédié
    c'est pas grave d'avoir un ADT juste pour ca (dans une appli - dans une lib, c'est mal, sauf si vraiment c'est un point business important de la lib)
    Yann Simon
    @yanns

    Coucou, petite question sur les existentiels types.
    Si j'ai:

    trait Obj[A, F[_]]
    
    def do1[F[_]](a: Obj[_, F])
    def do2[A](a: Obj[A, _])

    do1compile, mais do2 car F n'est pas un type simple.
    Y'a-t-il une syntaxe magique pour cela?

    Jonathan Winandy
    @ahoy-jon
    _[_] ?
    Julien Truffaut
    @julien-truffaut
    Si ca vous tente de faire une heure de Scala ce weekend, voici une video d’exercise ou l’on commence a implementer une parallel collection pour analyser un CSV de temperature. C’est aussi l’occasion de découvrir la librairie Kantan.csv de @nrinaudo et de s’entrainer a écrire des tests de propriétés
    https://youtu.be/VIxfSgl0-H4
    Jules Ivanic
    @guizmaii
    👋🙂