-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ListT is deprecated #245
Comments
I recall that (possibly in the paper?), the authors of monad-bayes were aware that Is there a reason we can't using one of the existing If not, shipping our own seems reasonable to me. And re. performance, I agree. I briefly tried refactoring with Vector, but the performance benchmarking was too hard for me. |
They generally work differently than what we want here. They allow for an effect after every element of the list, so it's more like a side-effectful stream. In fact,
I'll also see next week whether I can write a "set monad transformer" that is useful for us.
👍 I might look into that in the future. |
With help of the Berlin Haskell Users Group, I figured out that I didn't understand the situation about why For example, if you have: newtype ListT m a = ListT (m [a])
-- insert instance implementations here
failure :: Monad m => String -> ListT (Either String) a
failureList :: ListT (Either String) a
failureList = do
foo <- pure True <|> pure False
bar <- if foo then pure "late" else failure "early"
failure bar This can go along two paths, and on the first path it will fail late, while on the second path it will fail earlier. Bind on
|
The best free list transformer for this is probably https://hackage.haskell.org/package/free-5.1.3/docs/Control-Monad-Trans-Free-Ap.html#t:FreeT, which makes use of the |
There is also the Church transformed Is the lawlessness an actual problem here? That is, does the package either claim or require that the distribution representations be lawful monads? (similar question re. the Lazy sampler). Might be interesting to benchmark performance of What about |
@reubenharry 's reply is correct: monad-bayes only assumes (and provides) a monad structure, and the monad laws don't hold for the resulting structure. Shipping our own copy of It would be cool to have more performant implementations in the future --- I agree! |
Yes, they certainly don't. For reproduceability when debugging a sampler, or also a formal implementation like delayed sampling (#224), this can matter.
I don't agree. While it's true that the issue isn't as big as with, say,
Well, as a Haskell developer, I will always assume that of course anything that has a
Yes, I'll work on that next week.
It's hard to say yet. Part of a more extensive benchmark would be finding out what the typical usages of If there is much more |
Maybe the most appropriate thing to do is to put those big red warning letters then. In the paper we were quite explicit about using a monad structure rather than a monad. Type-classes don't really allow for re-use, in the sense that if we now need a completely separate type-class hierarchy for monad structure transformers, that will bloat up the code and make it a lot less maintainable and susceptible to bit-rot. And since Haskell doesn't really require, enforce, or use the monad laws for monad interfaces, the issue feels more ideological than pragmatic. In that case, perhaps it's better to hash out this issue on a Haskell mailing list or GitHub repo, rather than here, since it's a much broader issue than monad-bayes. |
I also feel that when something is a Monad, it should obey the monad laws. Wouldn't making use of qualified do-notation be a viable alternative than breaking monad laws? |
I'm not sure how the qualified do-notation helps here when what we're using is the existing monad-structure transformer ecosystem that postulates a Monad interface. |
I tried replacing the deprecated See #253 for details. So I think it's uncontroversial to replace |
The issue of looking into |
Is it correct though? |
Good question, I'm pretty sure that yes. Old
|
Thanks for the detailed explanation. First, can we please correct some imprecise assertions in it?
The semantics is well-defined, it is based on this paper that formally defines these data structures, the semantics of the inference algorithm, and proves that the result is an unbiased sampler.
I don't really follow this argument. Can you make it more precise please, for example, along the lines of the paper? The paper and its follow-up used the monad-structure transformer In general, free monads may do something different, for example, suspend random samples that some of the monad-bayes combinators do in crucial places. This might mean, for example, that using the same combinations of monad-bayes's building blocks to implement algorithms such as smc, smc^2 etc. are not longer correct. I suggest we first understand better how this proposed change affects the existing inference algorithms, not just in runtime, but in the actual samples they compute, both by testing and using an accompanying formalisation. |
My point is that Maybe the confusion is that
Note that all the existing test suites pass. Do you have suggestions for a more extensive test suite that we should implement first? |
Thanks for implementing additional tests! (Something is currently failing in the build, though.)
When we combine different inference building blocks, we do it before running Put differently, you argue that the monad laws used to fail and now they hold. We should hesitate to merge this kind of change without a more detailed analysis for how it affects the algorithms. |
Ah ok, I think I'm getting it now. Your last explanation helped me. Put yet differently, the way the other transformers push around the population can result in all sorts of bracketing of joins and binds, not necessarily coinciding with the canonical one chosen by |
I was mostly afraid of meddling with the semantics when I made changes to the library, but there are a couple of things that did change, that are perhaps worth noting:
I will say that subtleties like this make me wish the library was in Idris, and that the proofs of correctness were in the types. (I suspect that is something Ohad would like?). Even having worked with monad-bayes for a while, the correctness proofs of the inference algorithms is still beyond me. |
Situation
ListT
is deprecated since a long time, and has been removed from major packages:haskell/mtl#88
https://hackage.haskell.org/package/transformers-0.6.0.0/changelog
The reason it is deprecated is because for a noncommutative monad
m
,ListT m
famously is not a monad.m
needs to be commutative for it to be a monad, but that restriction is not enforced anywhere, so it was better to drop the whole construction.Situation for
monad-bayes
This also applies to randomness monads like we use here. Some monads like
Weighted
are commutative, but others really aren't. For example:While
mv1
andmv2
define the same probability distribution mathematically, they are not the same value. When we sample from them with the same random seed, they will produce different results. Sampling is not commutative.Side note: If we are only interested in statistics calculated from the samples in some kind of limit where we sample arbitrarily often, then we might not care about the difference. But if, for example, we want to reproduce some random sample path, the laws are broken.
Problems
Bit rot
The main problem arising from this situation is that
monad-bayes
slowly bit-rots because we cannot update dependencies. We have to restrict version bounds tomtl < 2.3 && transformers < 0.6
, which will eventually keepmonad-bayes
out of stackage and make it harder for everyone to use it.Broken laws
The side problem is also that right now we have a few functions that expose the breakage of monad laws: We have functions like
runPopulation
that expose the list order, so the broken monad laws can be observed.Performance
I haven't measured this yet, but I'll venture the guess that
ListT
is not very fast because it uses lists. Iterating over long lists of particles will incur some performance penalty.What could be done
Bit rot
We could ship our own
ListT
explicitly and thus remove the restrictive upper bounds onmtl
.Broken laws
The concrete order of the list elements must never be able to be observed. If we can only, e.g. sample a list element, or only retrieve all list elements in a fixed order, then this is fine. For example, these type signatures are ok:
These expose unlawful behaviour:
As far as I understand, a "set monad transformer" that doesn't expose the order of the elements would already be good. The minimal implementation that would achieve that would be restricting the interface as shown above. A more involved implementation would actually save the population as a
Map a (Log Double)
internally, which would have the additional advantage that duplicates could be eliminated.Performance
We might at some point want to investigate whether some kind of
Vector
can offer better performance. But that is not the main motivation behind this ticket.The text was updated successfully, but these errors were encountered: