TormentedDan
02/11/2020, 7:51 PMBob Glamm
02/11/2020, 7:59 PMTormentedDan
02/11/2020, 8:31 PMBob Glamm
02/11/2020, 10:10 PMF - that is, leaving everything as Kind<F, A> and providing the appropriate (typeclass) lower-bound for F that the class/trait/method in question requireBob Glamm
02/11/2020, 10:11 PMIO ) for F at the edge of the worldBob Glamm
02/11/2020, 10:13 PMT in ReaderT ) or custom combinatorsTormentedDan
02/11/2020, 10:25 PMkyleg
02/12/2020, 3:03 AMMonad<F>. But I don’t know how to derive a Kind from that.kyleg
02/12/2020, 5:33 AMfun <F, A> doSomething(): Kind<F, A> = TODO()
fun <F, A> doSomethingElse(): Kind<F, A> = TODO()
fun <F, A> doAComprehension(myMonad: Monad<F>): Kind<F,A> =
myMonad.fx.monad {
doSomething<F, A>().bind()
doSomethingElse<F, A>().bind()
}Jannis
02/12/2020, 12:30 PMKind<F, A>, that is impossible unless you know exactly what F is. The reason is pretty simply: Kind<F, A> is not a wrapped A! It is an action that produces an A with effects (effects meaning things like ForOption = Might be missing value effect, ListK = Might have multiple effect, IO = Anything, including side-effects etc. You can also view this as context, or other metaphors which are all equally bad 😄). Only if you know exactly what F is you can run those effects and get your A value out of it. (Option.fold(...), Either.fold(...), etc) And from some, like List or IO you "cannot" even get the value out because it has mutliple values or it has side-effects. In those cases typeclasses are needed to operator over the inside values.
Now if you have a completly polymorphic F, G, H you cannot compose them unless you have a few typeclasses that add such generic methods like Traverse (allows Kind<F, Kind<G, A>> => Kind<G, Kind<F, A>>) and a few others.
And lastly, if you have mutliple of those effects and you find yourself wrapping and unwrapping them constantly, it might be worth taking a look at mtl, but that is quite a bit more complex, but allows you to create stacks like Kind<F, Kind<G, A>> => Kind<Kind<F, G>, A> which also combines the types in a way and allows for easier use in comprehensions.TormentedDan
02/12/2020, 5:36 PMTormentedDan
02/12/2020, 5:39 PMTormentedDan
02/12/2020, 5:40 PMTormentedDan
02/12/2020, 5:58 PMJannis
02/13/2020, 1:44 PMDoes this have to do with ReaderT and WriterT?I have seen some explanations for these transformers but, tbh I think I'm going too fast. I need to get the basics first xD.Definitly basics first 😄 mtl is a good tool to use when you know how, but it can be hard to understand and in kotlin (until arrow-meta is in use) is not nice to use... Regarding the code: Not sure I understand what exactly the problem is, but a few things that might improve it anyway: • Avoid
val (_) = ... This will not work as expected in comprehensions, which is why we are deprecating it soon 😕 (The compiler thinks it can just run the coroutine without ever yielding back to the comprehension if the result is ignored)
• instead of attempt().flatMap { e -> e.fold(...) } why not handleErrorWith { e -> ... }TormentedDan
02/13/2020, 3:38 PMval (_) = ... bit? in other words, how do I force an IO to run inside a comprehension without binding it?Jannis
02/13/2020, 3:43 PMbind instead. Everything else that binds in comprehension is just an alias for that anywayTormentedDan
02/13/2020, 3:46 PM