[Haskell-cafe] Explicit approach to lazy effects For probability monad?
Benjamin Redelings
benjamin.redelings at gmail.com
Tue Oct 15 14:59:09 UTC 2019
Hi,
I'm wondering if people could point me to some background on explicitly
representing lazy effects in Haskell? The only effect I am concerned
about at this point is `seq`. If there is a way to do this with monads,
that would be great. (I know that a lot of people hate lazy effects.
However, I think this is an orthogonal issue to the question of how to
*represent* lazy effects explicitly.)
As background, I'm using a lazy probability monad where random sampling
is done with unsafeInterleaveST/IO (or something similar), so that
random variables are only sampled if they are actually used:
model = do
x <- sample $ normal 0 1 -- the interpreter does `unsafeInterleaveIO` to implement 'sample'
cond <- sample $ bernoulli 0.5
let y = if cond == 1 then x else 0
return y
Here, x is only sampled if cond==1. This has a lot of benefits in
procedures like Markov chain Monte Carlo.
I initially thought that I could model lazy effects by mapping a ->
(a,state) as in the ST monad. However, it seems like lazy effects
basically require allowing forked state threads to join CONDITIONALLY on
if a value is used/forced, and I don't see how to do that without a
source-to-source transformation of functions. It seems like lazy effects
require tracking state within each closure, and not globally within the
monad interpreter.
It kind of seems like this can't work if >>= has type 'm a -> (a -> m b)
-> mb', assuming m a = (a,state). The second argument needs to have
type (m a -> m b) instead of (a -> m b), since the computation needs to
have access to the state produced by the first "m a" computation, in
order to (optionally) depend on the state thread for first computation.
Does this make any sense? I don't know the literature in this area.
Q1. Is there a nice way of representing lazy effects that someone could
point me to?
Q2. Alternatively, is there a proof that either
(i) there is not a monadic way to represent lazy effects, or
(ii) fmap f requires a source-to-source transformation (for example
to explicitly join state threads on strict operations like ($) and case).
-BenRI
P.S. As even more background, I'm using a probability monad that allows
you to e.g. generate an infinite list of random variables, and only
instantiate the ones that are looked at:
model = do
n <- sample $ geometric 0.5
ys <- sample $ list (repeat $ normal 0.0 1.0)
zs <- take n ys
return (sum zs)
Here the number of random variables (n) can change over time, and I
ultimately want effects to happen when they are instantiated. There is a
brief overview at http://www.bali-phy.org/models.php
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20191015/52202685/attachment.html>
More information about the Haskell-Cafe
mailing list