<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Hi,</p>
    <p>I'm working on a probabilistic programming language with Haskell
      syntax [1].  I am trying to figure out how to intermingle lazy and
      strict monadic code without requiring ugly-looking markers on the
      lazy code.  Does anybody have insights on this?</p>
    <p>1. I'm taking a monadic approach that is similar to [2], but I'm
      using a lazy interpreter.  This allows code such as the following,
      which would not terminate under a strict interpreter:<br>
    </p>
    <pre>run_lazy $ do
  xs <- sequence $ repeat $ normal 0 1
  return $ take 10 xs
</pre>
    <p>Here "xs" is an infinite list of Normal(0,1) random variables, of
      which only 10 are returned.  In a strict interpreter the line for
      "xs" never completes. But in a lazy interpreter, it works fine.</p>
    <p>2. However, a lazy interpreter causes problems when trying to
      introduce *observation* statements (aka conditioning statements)
      into the monad [3].  For example,<br>
    </p>
    <pre>run_lazy $ do
  x <- normal 0 1
  y <- normal x 1
  z <- normal y 1
  2.0 `observe_from` normal z 1
  return y
</pre>
    <p> In the above code fragment, y will be forced because it is
      returned, and y will force x.  However, the "observe_from"
      statement will never be forced, because it does not produce a
      result that is demanded. <br>
    </p>
    <p>3. My current approach is to use TWO monads -- one for random
      sampling (Sample a), and one for observations (Observe a).  The
      random sampling monad can be lazy, because for random samples
      there is no need to force a sampling event if the result is never
      used.  The observation monad is strict, because all the
      observations must be forced.</p>
    <p>So this WORKS fine.  However... the code looks ugly :-(  Help?</p>
    <p>4a. One idea is to nest the lazy code within the strict monad,
      using some kind of tag "sample :: Sample a -> Observe a".  Then
      we could write something in the (Observe a) monad like:<br>
    </p>
    <pre>run_strict $ do
  w <- sample $ sequence $ repeat $ normal 0 1
  x <- sample $ normal 0 1
  2.0 `observe_from` normal x 1
  y <- sample $ normal x 1
  z <- sample $ normal y 1
  2.0 `observe_from` normal z 1
  return y</pre>
    <p>When the "run_strict" interpreter encounters a statement of the
      form (sample $ _ ), it switches to the "run_lazy" interpreter for
      that statement.<br>
    </p>
    <p>In this case, the `observe_from` statement IS forced because it
      is in the strict (Observe a) monad.  Maybe somewhat surprisingly
      w, x, y, and z are forced (ugh!) -- by the outer strict
      interpreter, not the inner lazy interpreter. However, the internal
      components of w are NOT forced, so the program is able to
      terminate.</p>
    <p>QUESTION: Is there some way of doing this without manually
      writing "sample" in front of all the sampling operations?</p>
    <p>QUESTION: is there a way of doing this where the "sample $ _"
      lines do NOT have their result forced?<br>
    </p>
    <p>4b. In order to write "sample" less, it is possible to factor the
      sampling code into a separate function (here called "prior"):<br>
    </p>
    <pre>prior :: Sample ([Double], Double, Double, Double)
prior = do
  w <- sequence $ repeat $ normal 0 1
  x <- normal 0 1
  y <- normal x 1
  z <- normal y 1
  return (w,x,y,z)

model :: Observe Double
model = do
  (w,x,y,z) <- sample $ prior
  2.0 `observe_from` normal x 1
  2.0 `observe_from` normal z 1
  return y
</pre>
    <p>This does mean that you have to write "sample" only once... but
      it (i) splits the function in half and (ii) forces you to
      explicitly pass (w,x,y,z) between the two functions.  That
      obfuscates the code for no benefit.<br>
    </p>
    <p>Interestingly, the logical conclusion of this movement of code
      from (Observe a) to (Sample a) is to move EVERYTHING to the Sample
      monad:</p>
    <pre>prior :: Sample (Observe (), Double)
prior = do
  w <- sequence $ repeat $ normal 0 1
  x <- normal 0 1
  let observations1 = [2.0 `observe_from` normal x 1]
  y <- normal x 1
  z <- normal y 1
  let observations2 = [2.0 `observe_from` normal z 1]++observations1
  return (observations2,y)

model :: Observe Double
model = do
  (observations, y) <- sample $ prior
  sequence_ observations
  return y</pre>
    <p>Now, we have moved all the observations into the (Sample a)
      monad, but using horrible syntax!  Ugh :-(  Also, now the function
      "model" is basically the same for all models -- the entire model
      has been moved into the prior.<br>
    </p>
    <p>QUESTION:  is there some way to write a monadic function like
      "prior" while accumulating things observations in a list?</p>
    <p>Thanks for any insights!<br>
    </p>
    <p>-BenRI<br>
    </p>
    <p>[1] <a class="moz-txt-link-freetext" href="http://bali-phy.org/models.php">http://bali-phy.org/models.php</a><br>
    </p>
    <p>[2] Practical probabilistic programming with monads, <a
        class="moz-txt-link-freetext"
        href="https://dl.acm.org/doi/10.1145/2804302.2804317">https://dl.acm.org/doi/10.1145/2804302.2804317</a></p>
    <p>[3] <a class="moz-txt-link-freetext" href="https://github.com/tweag/monad-bayes/issues/32">https://github.com/tweag/monad-bayes/issues/32</a><br>
    </p>
  </body>
</html>