``` fun <F> IO<F>.runner(connection: C...
# arrow
b
Copy code
fun <F> IO<F>.runner(connection: Connection): JDBCOps<F> =
        object: JDBCOps<F>, Fx<F> by this, Bracket<F, Throwable> by this {
doesn't work because Fx<F> is not Bracket
s
object: JDBCOps<F>, Concurrent<F> by this {
This is what you want. Don’t bother with
Fx
they’re being removed in
0.10
anyway. And you can currently also use it from
Concurrent
, in the next release
Fx
is merged into
Concurrent
.
Concurrent
also is
Bracket
inherited through
Async
.
So to reply on your last comment.
Copy code
fun <F> runner(connection: Connection, CF: Concurrent<F>): JDBCOps<F> =
        object: JDBCOps<F>, Concurrent<F> by CF {
            override val connection = connection
        }
I am not sure what you were using
Fx
for, or even which one since the package is missing. You can still drop the
Concurrent
constraint to
Async
or just
Bracket
depending on what you use
Fx
for currently.
b
Well, I was using
Fx
for
fx
. The following type-checks but I'm not sure if the usage of
fx.monad
below is intended:
Copy code
interface JDBCOps<F>: Bracket<F, Throwable> {
    val connection: Connection

    fun <A> withStatement(query: String, rsMapper: (ResultSet) -> Kind<F, A>): Kind<F, A> =
            fx.monad { connection.createStatement() }.bracket(
                    { stmt -> fx.monad { stmt.close() } },
It seems right since I do want sequential execution of the contained programs? It just looks a little weird
s
Okay, so we had the issue with
Fx
that it was import based. Which people found very confusing to use, the reason we did so was so we could enable syntax through the receiver type of
fx { }
.
As a compromise we’ve incorporated
fx
into the typeclasses themselves but you have to specify which syntax you want enabled. There is
monad
,
monadFilter
,
concurrent
,
async
, .. depending on which typeclass you’re using. Besides that there is no difference.
Here you are using
fx.monad { connection.createStatement() }
as
effect { connection.createStatement() }
or at least that’s what it looks like to me.
b
yes, although I'm not necessarily tied to
fx
. For new code is it just better to use something like
effect
?
s
effect
is to wrap impure code (including
suspend
).
fx
is typically used for
bind()
or
!
.
b
Ok, so is it fair to say that the
fx.BLAH
syntax is simply selecting some level of monad to use - e.g.
fx.async
says I need a monad instance that at least supports the async effect?
s
Any typeclass that inherits from
Monad
has a property
val fx
, but depending on which typeclass you’ll be able to enable more or less syntax. For example.
Copy code
fun <F> exampleOne(AS: Async<F>): Kind<F, Unit> = AS.fx.async { // receiver of type `AsyncSyntax<F>
  continueOn(CommonPool)
  just(Unit).bind()
}

fun <F> exampleOne(AS: Async<F>): Kind<F, Unit> = AS.fx.monad { // receiver of type `MonadSyntax<F>
  // continueOn(CommonPool) <-- not available for MonadSyntax
  just(Unit).bind()
}
And obviously
Monad
cannot enable
fx.async
b
Ok, I think that makes it a little clearer
The other odd thing I noticed is that the following type-checks:
Copy code
fun <F> runner(connection: Connection, BF: Bracket<F, Throwable>): JDBCOps<F> =
        object: JDBCOps<F>, Bracket<F, Throwable> by BF {
...
fun foo(c: Connection) {
    runner(c, IO.bracket())
}
but removing the
BF
parameter and replacing
by BF
with
by IO.bracket()
does not