[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