If I have a `Kind<F, A>` (and its `Monad<...
# arrow
s
If I have a
Kind<F, A>
(and its
Monad<F>
as well), how do I pry out the value of type
A
? In other word, how would I implement this extension function?
Copy code
fun <F,A> Kind<F,A>.evaluateKind(monad: Monad<F>): A {
    // TODO Get and return the 'A' typed value from 'this' Kind<F,A>
}
b
I'm not sure that even makes sense as a type signature. For instance, if
F
was
Option
and the value for
Kind<F,A>
was
Option.None
what would the return value of
A
be?
s
Is there a way to convert a
Kind<F,A>
to a
Try<A>
then, basically changing the
F
to a constructed
Try
?
Or to an
Option<A>
? Or even
A?
🙂
r
Kind<F, A> -> A
it's Comonad
extract
but it does not apply to the types you are dealing with. That function can't be implemented without blocking or throwing exceptions. That is why it's suspended. What you want is
bind
but it will always return the value back in the wrapper.
@streetsofboston do you have a small illustrative example?
What you want is available as part of the UnsafeRun type class but only IO and Fx provide extensions for it
s
E.g
Copy code
fun <F,A> sideEffectValue(monad: Monad<F>, f: suspend () -> A): Kind<F, A> {
    return monad.fx { !effect(f) }
}

fun main() {
    val ioValue = sideEffectValue(IO.monad()) { "Hello" }
    val eitherValue = sideEffectValue(Either.monad<Int>()) { "Hello "}
}
How would I be able to pry the value out of the
ioValue
or the
eitherValue
, if the only thing I know they are a
Kind<F, String>
?
r
in the case of IO it's:
Copy code
import <http://arrow.effects.IO|arrow.effects.IO>
import arrow.unsafe
import arrow.effects.extensions.io.unsafeRun.runBlocking
import arrow.effects.extensions.io.fx.fx
suspend fun sayHello(): Unit =
  println("Hello World")
  
suspend fun sayGoodBye(): Unit =
  println("Good bye World!")
  
fun greet(): IO<Unit> =
  fx {
    !effect { sayHello() }
    !effect { sayGoodBye() }
  }

fun main() { // The edge of our world
  unsafe { runBlocking { greet() } }
}
but in the case of Either is not safe
s
The example above is fixed to
IO
. I could use
Function0
as well. How can I make this agnostic on which one is exactly used?
r
UnsafeRun
Copy code
@extension
interface IOUnsafeRun : UnsafeRun<ForIO> {

  override suspend fun <A> unsafe.runBlocking(fa: () -> Kind<ForIO, A>): A = fa().fix().unsafeRunSync()

  override suspend fun <A> unsafe.runNonBlocking(fa: () -> Kind<ForIO, A>, cb: (Either<Throwable, A>) -> Unit) =
    fa().fix().unsafeRunAsync(cb)

}
that is the IO instance, you can create as many for all the types you want to support.
s
Thank you! That is what I was looking for. 🙂
r
Arrow only declares unsafe runners for monad that are effectful and Either is not one of them
s
I see. Maybe wrong example. I was talking more about
IO
,
Function0
, and other ‘effectful’ monads.
r
Note that the fact that you want to do this for Either shows your program is not composed properly.
s
That could very well be 🙂 I’m a beginner
r
ok, if they are suspend capable monads then yeah and you may want to consider PRs for the UnsafeRunners you create
As we are still working through Fx we have only those two instances
s
Thank you for your help!
Todavia estoy aprendiendo. No es facil, pero me estoy mejorando 🙂
👏 2
r
nice spanish! No worries, I guess what I ment to say is that if you are in the context of an effectful program and you have an
Either
value for example you can get
A
on the right by calling
either.getOrRaiseError { throw it }
that gives you the right of the Either or raises an error in the context of F
But if you want to polymorphically unsafe run data types you need those instances.