Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Ignore how badly written the project is in general; Is it useful to turn the steps not dependent on eachother into mapNs?
Raas Ahsan
@RaasAhsan
  1. AFAIK there isn't, for comprehensions always desugar into a series of nested flatMaps. not sure if there are compiler plugins that do otherwise
  2. mapN will evaluate effects in the order in which they appear in the tuple
  3. likely not, Applicative functions for Monads are usually written in terms of flatMap
Soren
@srnb_gitlab
@RaasAhsan What about IO? Isn't there this thing where mapN on IO/Task parallelize?
Raas Ahsan
@RaasAhsan
it will for Parallel operations like parMapN, but the regular Applicative instances will evaluate sequentially
Soren
@srnb_gitlab
Hmm
Raas Ahsan
@RaasAhsan
mapN will evaluate multiple independent effects sequentially, parMapNwill evaluate multiple independent effects in parallel
Soren
@srnb_gitlab
Can I say "use parMapN if possible, otherwise mapN"?
Raas Ahsan
@RaasAhsan
I think that's reasonable :) but if the effects are very fast to compute or don't involve I/O, the overhead of shifting executors might cause parMapN to be slower
Soren
@srnb_gitlab
hmm
the effects will be very fast to compute so :+1:
I'll just use a for loop
comp
Alex Henning Johannessen
@ahjohannessen
Thanks @tpolecat :)
Enrico Benini
@benkio

A question

https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/data/WriterT.scala#L330

In here liftF requires an Applicative, but it just uses map, why it just don't require a Functor instance?
Cheers

Gavin Bisesi
@Daenyth
Looks likely to be an error.
1 reply
Ethan
@esuntag
@srnb_gitlab I get joy out of overengineering hackerrank type problems. In this case what it boils down to is you start with an array of Int, and a target value, and you want to find the two values that add up to the target.
def compute[A: Monoid, F[_]: Foldable: Comonad](fa: F[A], target: A): Option[String] = 
    fa.coflatten.foldMapK(f => {
      val a = f.extract
      f.foldMapK(b => Option.when((a |+| b) == target)(s"$a $b"))
    })
Gavin Bisesi
@Daenyth
oh my
wonder what the asymptotics are on that using list/vector vs zipper
"find the two values" is that pairwise values?
or any two values?
Ethan
@esuntag
There's guaranteed to be a unique solution, so there will be precisely two numbers in the initial array that add up to the target. Still missing the semantics in that disallowing selecting the same one twice, not sure if there's something better than a filter for that
Don't worry, this is going nowhere near production
Ethan
@esuntag
For example, compute(NonEmptyList(1,List(,2,3,4,5)),9) should give 4 5
Steven Fines
@sfines-clgx
alright, it is time for Steve's stupid Cats Question of the day:
say I have a list, and I want to use a functor to filter, then compute on the list, what is the best way to do that? logically to me it seems like it should be compose, but that seems to want a List[List[]] instead of composing two functions
Christopher Davenport
@ChristopherDavenport
You probably just want FunctorFilter
Steven Fines
@sfines-clgx
where is that in the docs?
You can use collect with a PartialFunction to filter and compute in one go
Steven Fines
@sfines-clgx
cool. That wasn't on the main docs page ;)
that is exactly what I want
Christopher Davenport
@ChristopherDavenport
Always more to document. PR's appreciated. :smile:
Adrian
@adrian-salajan
hi, i can't find the Eq instances for Array. any gotchas ?
Gavin Bisesi
@Daenyth
might be in alleycats
One gotcha is that unlike most of scala, Array uses reference equality for ==
You compare values with sameElements
James Earl Douglas
@earldouglas
Does cats have a memoization wrapper like scalaz's Memo? Eval is close, but looks like it only memoizes thunks. I need to memoize a function1.
Jacob Wang
@jatcwang
@earldouglas I'm not aware of one in cats directly, but https://monix.io/docs/current/eval/coeval.html
Aloïs Cochard
@aloiscochard
hey there, taking inpsiration from the release process of cats (and usage of sbt-release). I do wonder how developer manage and set which GPG key should be used when publishing/releasing locally? cheers
Gavin Bisesi
@Daenyth
I think that's handled by sbt-pgp (or is it sbt-gpg?)
docs for that plugin should point you
Rob Norris
@tpolecat
@aloiscochard I highly recommend sbt-ci-release. It has doc for the whole process. I have been using it for a while.
Also hi o/
Aloïs Cochard
@aloiscochard
hi @tpolecat :), that plugin is really nice and seems to sum up all the best practice in order to sign and publish from TravisCI ty! But looking at this job from last tag: https://travis-ci.org/github/typelevel/cats/builds/723799804 I am under the impression that cats is not using this approach but instead rely on developers/maintainer doing sbt release, we quite like that as this prevent potentially leaking GPG key and passphrase to the CI vendor.
so this get me curious, how does people doing the release of cats do with their GPG configuration? my current thinking is that they do it in their global.sbt in their home directory.
Rob Norris
@tpolecat
I’m not sure. @kailuowang or @LukaJCB could tell you.
Luka Jacobowitz
@LukaJCB
I’ve never actually cut a cats release, but I’m pretty sure that’s how it’s done yeah
Aloïs Cochard
@aloiscochard
thanks for the help and the insights folks!
Daniel Spiewak
@djspiewak

@aloiscochard I have thoughts on this! :-D

First off, sbt-gpg >>> sbt-pgp. To the extent that a lot of key management is simply impossible with sbt-pgp, so I'm just going to assume the former.

My personal GPG keys are split and air gapped, and the master key has never existed on a network-connected machine, even encrypted. The signing key is on my yubikey, with the stubs and public keys on my laptop. I used gpg itself to configure this as the primary signing key (using the default-key configuration). This is sufficient for sbt-gpg to pick it up.

I believe pretty strongly in doing local releases for OSS because of the attribution it provides, since attribution and reputation are technically the only trust mechanisms we have to go on. I realize basically no one actually validates signature checks in OSS (other than me…), but it would be nice if that situation could improve (I have ideas on this too! but no time…). CI releases are profoundly convenient though, and I do them for all my work projects. There's also something to be said about the fact that @ChristopherDavenport actively maintains approximately a million libraries, and credits ci-release for making that possible.

If you're doing ci-releases, you want to create a bespoke signing key for your organization that isn't used for anything else. It should have a bot email, etc etc. Sign it with your key and publish that signature. Then encrypt the organizational signing key in GH Actions (or TravisCI)'s secrets (random fyi: Actions is now vastly preferable to Travis if you have a choice, and I say that as someone who used TravisCI quite heavily for a long time). This does leak the private key to the CI infrastructure itself, but since it's a bespoke key that is only used for publishing releases (something you already want the CI to be able to do), it's less of a security risk. Note that it also technically leaks the private key to any maintainers who can push to the upstream fork, but they can't extract it without performing a highly visible action (making and pushing a commit), and you can then revoke.

Looping back… I don't have a global.sbt or anything like that. I've been bitten pretty hard by the global sbt config in the past. It's all just done with native gpg configuration.