<div><font face="courier new,monospace">Hi everyone... it's my newbie post!</font></div>
<div><font face="courier new,monospace"></font> </div>
<div><font face="courier new,monospace">I am trying to create a monad which allows computations to output data to a stream. (Probably such a thing already exists, but it's a good problem for my current skill level in Haskell)
<br> </font></div>
<div><font face="courier new,monospace">For example:<br></font></div>
<div><font face="courier new,monospace">streamDemo = do<br> output 1<br> output 2<br> output 5<br></font></div>
<div><font face="courier new,monospace">makelist streamDemo -- [1,2,5]<br></font></div>
<div><font face="courier new,monospace">I modelled my implementation around the state monad, but with a different execution model:</font></div>
<div><font face="Courier New"></font> </div>
<div><font face="courier new,monospace">class (Monad m) => MonadStream w m | m -> w where<br> output :: w -> m ()<br> run :: m a -> s -> (s -> w -> s) -> s -- basically foldl on the stream values
<br>makelist m = reverse $ run m [] (flip (:))<br><br>-- s is the type of the object to stream, r is the return type<br>type StreamFunc s r = forall b. b -> (b -> s -> b) -> (r,b)<br>newtype Stream s r = Stream { run' :: StreamFunc s r }
<br>instance Monad (Stream s) where<br> return r = Stream (\s _ -> (r,s))<br> Stream m >>= k = Stream (\s f -> let (r,s') = (m s f)<br> in run' (k r) s' f)<br>instance (MonadStream w) (Stream w) where
<br> output w = Stream (\s f -> ((),f s w))<br> run m st f = snd $ run' m st f<br> </font></div>
<div><font face="courier new,monospace">What I don't like is how makelist comes out. It feels wrong to need to use reverse, and that also means that infinite streams completely fail to work. But I think it's impossible to fix with the "foldl"-style "run". Is there a better implementation of "makelist" possible with my current definition of "run"? If not, what type should "run" have so that it can work correctly?
</font></div>
<div><font face="courier new,monospace"> </font></div>
<div><font face="courier new,monospace">As an example, I want to fix the implementation to make the following code work:</font></div>
<div><font face="courier new,monospace">fibs :: Stream Integer ()<br>fibs = fibs' 0 1</font></div>
<div><font face="courier new,monospace"> where fibs' x y = output y >> fibs' y (x+y)<br></font><font face="courier new,monospace"></font></div>
<div><font face="Courier New">fiblist :: [Integer]</font> </div>
<div><font face="courier new,monospace">fiblist = makelist fibs</font></div>
<div><font face="courier new,monospace"></font> </div>
<div><font face="courier new,monospace">take 5 fiblist -- [1,1,2,3,5], but currently goes into an infinite loop</font></div>
<div><font face="courier new,monospace"></font> </div>
<div><font face="courier new,monospace">Thanks,</font></div>
<div><font face="courier new,monospace"> -- ryan</font></div>