Currently there are at least four concurrency primitives, whose initialization delayed in another layer of effect:
Deffered, MVar, Ref and Semaphore
In some real-world applications initialization of such states happens in different monad than actual application logic.
Simple example:
Ref[Task]s and MVar[Task]ReaderT[Task, ApplicationContext] where ApplicationContext could contain some of initialized Ref's and MVar'slift on every put, take and modify This has annoying effect of transforming every invocation of Ref, MVar, Deffered method from Task to the target monad. In case of tagless final style using two functorial type parameters is even more unpleasant.
There are still some considerations:
.delay onlyI can see two solutions here:
scala
object MVar{
// ...
def create[F[_]: Sync, G[_]: Concurrent](initial: A): F[MVar[G, A]]
// ...
}
I'm eager to implement both.
I'm kind of 馃憥 on constructors, but mapK doesn't sound awful.
I generally write a mapK in the companion object rather than on the class, but I'm not opposed.
I generally write a
mapKin the companion object rather than on the class, but I'm not opposed.
I would rather make an integration with cats-tagless when it will be ready.
Not sure what cats-tagless does, but introducing extra dependencies in cats-effect is a tough sell. Because it is middle-ware and other libraries depend on it. I'm worried that cats is too fat for example.
I just ran in to a use case for this when working with Scala.js -- specifically, I'd like to create things like Ref[IO, A] in SyncIO so I'm guaranteed to be able to create my refs synchronously. Note the mapK solution doesn't apply to this use case.
If I understood correctly, the majority of #388 reviewers are ok with mapK and some are ok with dual effect constructors and only dual effect can help in @mpilquist 's issue.
So I'm dgoing to do two distinct PR's . One for mapK and one for dual constructors.
Is that right way?
I mean, I think mapK is a good thing to have anyway. :-)
With #392 and #393 being merged I think this one is solved.
Most helpful comment
I just ran in to a use case for this when working with Scala.js -- specifically, I'd like to create things like
Ref[IO, A]inSyncIOso I'm guaranteed to be able to create my refs synchronously. Note themapKsolution doesn't apply to this use case.