Hi Phil,<br><br><div class="gmail_quote">On Mon, Jun 15, 2009 at 5:23 PM, Phil <span dir="ltr">&lt;<a href="mailto:phil@beadling.co.uk">phil@beadling.co.uk</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hi,<br><br>I&#39;m trying to think around a problem which is causing me some difficulty in Haskell.<br><br>I&#39;m representing a stateful computation using a State Transform - which works fine.  Problem is in order to add flexibility to my program I want to performs the same operation using different techniques - most of which require no state.<br>

<br>My program at the moment is a stack of state monads/transforms.  I have a random number generator as a state monad (seed=state), feeding a Box Muller (normal) generator implemented as a state transform (state is &#39;maybe&#39; normal, so it only spits out 1 normal at a time), which in turn feeds another state machine.<br>

<br>This all works fine, but I want to add flexibility so that I can chop and change the Box Muller algorithm with any number of other normal generators.  Problem is most of them do not need to carry around state at all.<br>

This leaves me with a messy solution of implementing lots of state monads that don&#39;t actually have a state, if I want to maintain the current paradigm.<br><br>This strikes me as really messy - so I&#39;m hoping someone can point me in the direction of a more sensible approach?</blockquote>
<div><br>I&#39;m interested in how you solve this, but I didn&#39;t see any replies yet so I thought I would toss in my thoughts.<br> <br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
<br>Currently I have my Box Muller implemented as below - this works:<br><br>class NormalClass myType where<br>  generateNormal :: myType Double <br></blockquote><div><br>This type class might be at the heart of your difficulties.  I think it requires myType to have kind * -&gt; * and it doesn&#39;t specify what the input to generateNormal should be.  I also notice you&#39;re not using it later in the example code which is another warning sign.<br>
 </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>type BoxMullerStateT = StateT (Maybe Double)<br>type BoxMullerRandomStateStack = BoxMullerStateT MyRngState</blockquote>
<div><br>You used &#39;type&#39; here, but I bet you want &#39;newtype&#39; with the newtype deriving feature/extension.  Otherwise, this nice neat stack of transformers that you have is fixed to just one instance of NormalClass, but I suspet you may have multiple ways to generateNormal that use the same stack of transformers.<br>
 </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>
<br>instance NormalClass BoxMullerRandomStateStack where<br>  generateNormal = StateT $ \s -&gt; case s of<br>                  Just d  -&gt; return (d,Nothing)<br>                  Nothing -&gt; do qrnBaseList &lt;- nextRand<br>

                                        let (norm1,norm2) = boxMuller (head qrnBaseList) (head $ tail qrnBaseList)<br>                                        return (norm1,Just norm2)<br><br><br>But say I have another instance of my NormalClass that doesn&#39;t need to be stateful, that is generateNormal() is a pure function.  How can I represent this without breaking my whole stack?<br>

<br>I&#39;ve pretty much backed myself into a corner here as my main() code expects to evalStateT on my NormalClass:<br><br>main = do let sumOfPayOffs = evalState normalState (1,[3,5]) -- (ranq1Init 981110)<br>                where <br>

                  mcState = execStateT (do replicateM_ iterations mc) 0<br>                  normalState = evalStateT mcState Nothing</blockquote><div><br>If it is useful to define generateNormal, then why don&#39;t you use it here?<br>
<br>What if we go back to your NormalClass type class and redesign it?<br><br>If we add a parameter to the type class which depends on the way you implement generateNormal I think we&#39;d be most of the way there.  I&#39;m also going to remove the explicit &#39;Double&#39;, and let that be part of the type of &#39;myType&#39;.  Untested, but I think this is the syntax for using multiparameter type classes and functional dependencies:<br>
<br>class NormalClass seed myType | myType -&gt; seed where<br>  generateNormal :: seed -&gt; myType<br><br>type Seed = ... -- Whatever type the seed has currently<br><br>instance NormalClass Seed (Maybe Double) where<br>
  generateNormal seed = evalState (StateT $ \s -&gt; case s of<br>                  Just d  -&gt; return (d,Nothing)<br>                  Nothing -&gt; do qrnBaseList &lt;- nextRand<br>
                                        let (norm1,norm2) = boxMuller (head qrnBaseList) (head $ tail qrnBaseList)<br>                                        return (norm1,Just norm2)) seed<br><br>-- An arbitrary &#39;pure&#39; example<br>
instance NormalClass () Double where<br>  generateNormal () = 1.0<br><br>Ah, now I see a problem with this approach.  You&#39;ll end up putting a newtype on the return value of generateNormal just to allow different instances.  I sort of feel like the way things are designed we are assuming we have subtyping, but Haskell doesn&#39;t have that.  <br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br><br>If it wasn&#39;t for this I was thinking about implementing the IdentityT transformer to provide a more elegant pass-through.<br>

I&#39;ve never tried designing my own Monad from scratch but this crossed my mind as another possibillity - i.e. a Monad that either has a state of maybe double, or has no state at all?</blockquote><div><br>I have a feeling I&#39;d just &#39;return&#39; the pure computations into the state monad.  My example code above seems weird and heavy weight to me.<br>
<br>I&#39;d love to see what you figure you.<br><br>Jason<br></div></div><br>