hi @dialelo following on from https://github.com/funcool/cats/issues/75 am i missing something obvious ? i've currently got some code using a Deferred[Either] monad (Deferred being my own creation v. similar to canal but for manifold Deferreds rather than core.async chans), and i'd like to use alet instead of mlet for the async concurrency gains...
I know that in monads this is resolved using monad transformers, but I'm not know it the same concept applies to your situation
In any case, the manifold deferred already has the notion of error
so the usage of the either it make sense?
i'm not using the manifold error - they are being converted to either/left values
The question is, why not use builtin error facilities of the async value primitives that you are using?
(is just curiosity)
because then i get the either short-circuiting behaviour in multi-step computations
0.o, this is also can be get with builtin error handling
I'm currently using promissum
with the CompletableFuture of jdk8
and I get the desired short-circuiting directly
without using either
ah, yeah, good idea - i could use the on-error behaviour directly in the Deferred monad
yeah...
the either is not necesarry if the abstraction already has a concept of the error
I'm not pretty fan of manifold deffereds
what don't you like about deferreds ?
I prefer using something like this https://github.com/funcool/promissum
i'm using aleph, so deferred was an obvious choice for an async primitive
yeah, but the manifold documentation is obscure and only based on code examples or api reference
It is a great library, sure. I don't have strong arguments for say bad things
it is just I don't like libraries without comprensible human readable documentation
did you see : https://github.com/ztellman/manifold/blob/master/docs/deferred.md
Yes. Do you think this is a complete documentation...? is a simple readme
that only covers the "quick start"
yeah, they are quite basic. though deferred is quite a simple concept. the stream docs are worse and i had to do more code-reading there
The concept is very simple. You are right. But it not means simple concepts should not to be documented.
On the end... is my opinion... nothing more
\o/
ha, well i'm certainly not complaining about better docs, and the funcool libs i've used have great docs
(them being cats and buddy)
Is one of the main goals of funcool org...
the docs are not only about code examples. Are about how to install, how to contribute, the tricky cases, advaced use cases, the project maturity, quick start...
exactly, the situation is improving a bit but many Clojure libraries suffer from lack of good documentation
\o @dialelo
o/
@mccraigmccraig: have you ended up using deferred's built-in error handling facilities?
@dialelo: i haven't , i'm using Either atm with a monad-transformer
i could use them though
which would get me out of needing to combine applicatives
so you want to be using Deferred[Either]
inside an alet
block and have: short-circuiting (from Either) and the bindings be the right values of either, am i right?
yeah, that was the idea... is that sane ?
or insane :simple_smile:
seems reasonable to me, although if your async abstraction already supports error handling i'd go with it
from what i read applicatives compose automatically like functors
but i need to experiment using multiple applicative "layers" inside alet
yeah, from what i've read they can be composed generically, and each type doesn't need it's own transformer
there would still presumably need to be something which reified the composed applicative though ?
yep, I guess we have to implement a applicative type for nested applicatives
i can sidestep the problem for now by using manifold's error-handling though
great, I'm going to spend some time investigating nested applicatives
since there are already monad-transformers, it might make sense to add the applicative nesting to those... even if the implementation is just a call to a generic impl
definitely, i'm going to add that as an issue to cats
well, there is an issue already
the one you opened
sorry, just woke up :simple_smile:
:simple_smile:
i've been thinking i might want to add a writer to my contexts at some point (the thing that brought me to wanting alet is a high-level async cassandra client) to trace exactly what happened in a given op, so when i get around to that i won't be able to sidestep it in the way i can here
you mean the writer monad?
yeah... it's on a holiday from cats atm is it ?
you could also use an agent for logging, you get ordering semantics
@niwinz is going to add it back
but in our opinion is one of the things that can be achieved more idiomatically in Clojure
and doesn't provide much value in an "impure" language
of course we may be wrong, we're learning about all these abstractions by writing the library
true - this async stuff is the first thing i've done in clojure where there is real obvious value in the monad abstractions over and above other stuff already in the language
but then, once you've drunk the kool-aid, there seems to be value in being able to compose concepts and be able to rely on tested implementations which are designed to compose
though it's early days for me - i'm learning the abstractions to avoid going insane from callback hell :simple_smile:
so a mixed approach may well be best for clojure
yes, it is definitely valuable to compose these abstractions although our context management strategy needs improvements for making them easier to use
but stacking monads through transformers can get complicated once you have more than two layers
i think a mixed approach is best for Clojure
use monadic types for things like asynchronous computation and error handling
logging, state management and such are well solved problems in Clojure
so although we implemented reader, writer and state we didn't found ourselves using them at all
ah, ok, i wondered why you took them out
i'm currently looking at http://hackage.haskell.org/package/TypeCompose-0.9.10/docs/src/Control-Compose.html#%3A. for composing 2 applicatives or functors
but don't worry, they are going in under the cats.labs
namespace for the next release
interesting to hear of your experience implementing reader/writer/state and finding you were not using them... i guess i may well find the same... dunno yet. it's all pretty new to me :simple_smile:
one thing to be aware of when using composed applicatives in alet
is that alet
uses the monadic bind for removing applicative layers
with cats.core/join
so composed applicatives, in most cases, need to be monad transformers too
except in very simple alet
bindings
which are compiled down to an fmap
i see that in our transformers we don't define the applicative instance, i'm opening an issue to solve that
i've started working on implementing functor and applicative for every transformer we provide
this way composing them and using them in alet
will be possible and easy
oh, awesome... that will be handy - i'll stick with Either for error handling then... i'm already using Either for error handling in my web layer, so somewhere in my stack i will have to convert from manifold to Either error handling anyway
however i don't know when the PR will be ready, today i'm going to work on the core protocols chapter for the CLJS book we're writing https://github.com/funcool/clojurescript-unraveled/pull/98
that will have me busy for a few days i think
i kickstarted the applicative work in this PR https://github.com/funcool/cats/pull/77
so if @niwinz or yourself want to work on it i'll be happy to review!
ok, well i'm not blocked atm, because the monad-transformer impl i have working at the moment works fine... it's just a bit slower than it could be because it's not concurrent enough. if i get to the point of being blocked, or i need a diversion, then i'll have a go at some of the other monads
great, just merged it
Thanks!