<div dir="ltr">All you need is the state to have different "aspects" <div><br></div><div>You can express this with parameters to your stateful computations<div><div><br></div><div>Here's an (uncompiled) sketch covering part of your case, using lenses</div><div><br></div><div>{-# language TemplateHaskell #-}</div><div><br></div><div>import Control.Lens (Lens', set, makeLenses)</div><div>import System.Random</div><div>import Control.Monad.State</div><div><br></div><div>-- a user of any state 's' which has  a StdGen aspect, see the 's' is free here so putGen is polymorphic in it</div><div>putGen :: Lens' s StdGen -> StdGen -> State s  ()</div><div>putGen l g = modify $ set l g</div><div>-- or for shorter see Control.Lens.Setter</div><div>-- putGen = (.=)</div><div><br></div><div>...</div><div>...</div><div><br></div><div>-- a state as a record with all aspects</div><div>data S = S {</div><div>  .... :: ....</div><div> , _generator :: StdGen</div><div>  ..... :: ..</div><div>}</div><div><br></div><div>makeLenses ''S -- automatically derive the lenses for you (generator function in example)</div><div>-- equivalent at least  to something like</div><div>-- generator f g s = (\g' -> s{_generator = g'}) <$> f g</div><div><br></div><div>main = do</div><div>  g0 <- newStdGen</div><div>  print $ evalState (putGen generator g >> ....) $ S ... g0 ..</div><div> </div><div>(This leaves you the burden of passing lenses around (one for each aspect) which you could alleviate with different techniques, if this is ever a concern)</div><div><br></div><div>As Tom said, typeclasses are not that good for this cases as it might seem at first glance</div><div><br></div><div>HTH</div><div><br></div><div>Best</div><div><br></div><div>paolino</div><br><div class="gmail_quote"><div dir="ltr">On Thu, 28 Jun 2018 at 07:23, Dennis Raddle <<a href="mailto:dennis.raddle@gmail.com">dennis.raddle@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>I'm writing a program with several functions, some of which depend on certain fields in a state monad, others of which depend on others, but no routine needs all the fields. <br></div><div><br></div><div>So I thought I would declare a two classes, one for each type of data need that a function has:</div><div><br></div><div>-- as an aside, here's an example of data which is parameterized by two types. <br></div><div><br></div><div>data ReportData t1 t2 = ...<br></div><div><br></div><div>-- this is rolling my own state monad with a random generator<br></div><div>class Monad m => RandMonad m where</div><div>   getGen :: m StdGen</div><div>   putGen :: StdGen -> ()</div><div><br></div><div>-- this is a class of state monad which logs ReportData:</div><div><br></div><div>class Monad m => LogMonad m where</div><div>   putReport :: ReportData t1 t2 -> m ()</div><div><br></div><div>For a particular use case, I declare a type of State monad:</div><div><br></div><div>data MyStateData t1 t2 = MyStateData t1 t2<br></div><div>  { theGen :: StdGen</div><div>  , theReports :: [StepReport t1 t2]</div><div>  }</div><div><br></div><div>type MyState t1 t2 = State (MyStateData t1 t2)</div><div><br></div><div>And I try to define my instances:</div><div><br></div><div>instance RandMonad (MyState t1 t2) where</div><div>  getGen = gets theGen</div><div>  putGen g = modify (\s -> s { theGen = g})</div><div><br></div><div>instance LogMonad (MyState t1 t2) where</div><div>  putReport r = modify (\s -> s { theReports = r : theReports s})</div><div><br></div><div>I get an error on the LogMonad instance, saying that there's no instance for (MonadState (MyState t1 t2) (StateT (MyState t1 t2) Identity))</div><div><br></div><div>I guess I don't really understand typeclasses once you start using higher kinded types, so please enlighten me. Any reading on this subject would be helpful, too.<br></div></div>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</blockquote></div><br><div><br></div><div><br></div></div></div></div>