Hi Phil,<br><br><div class="gmail_quote">On Mon, Jun 15, 2009 at 5:23 PM, Phil <span dir="ltr"><<a href="mailto:phil@beadling.co.uk">phil@beadling.co.uk</a>></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'm trying to think around a problem which is causing me some difficulty in Haskell.<br><br>I'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 'maybe' 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't actually have a state, if I want to maintain the current paradigm.<br><br>This strikes me as really messy - so I'm hoping someone can point me in the direction of a more sensible approach?</blockquote>
<div><br>I'm interested in how you solve this, but I didn'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 * -> * and it doesn't specify what the input to generateNormal should be. I also notice you'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 'type' here, but I bet you want 'newtype' 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 -> case s of<br> Just d -> return (d,Nothing)<br> Nothing -> do qrnBaseList <- 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'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'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'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'd be most of the way there. I'm also going to remove the explicit 'Double', and let that be part of the type of 'myType'. Untested, but I think this is the syntax for using multiparameter type classes and functional dependencies:<br>
<br>class NormalClass seed myType | myType -> seed where<br> generateNormal :: seed -> 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 -> case s of<br> Just d -> return (d,Nothing)<br> Nothing -> do qrnBaseList <- nextRand<br>
let (norm1,norm2) = boxMuller (head qrnBaseList) (head $ tail qrnBaseList)<br> return (norm1,Just norm2)) seed<br><br>-- An arbitrary 'pure' example<br>
instance NormalClass () Double where<br> generateNormal () = 1.0<br><br>Ah, now I see a problem with this approach. You'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'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't for this I was thinking about implementing the IdentityT transformer to provide a more elegant pass-through.<br>
I'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'd just 'return' the pure computations into the state monad. My example code above seems weird and heavy weight to me.<br>
<br>I'd love to see what you figure you.<br><br>Jason<br></div></div><br>