[Haskell-beginners] Is there such a thing as a lazy monadic list?

Elvio Toccalino elviotoccalino at gmail.com
Mon May 9 15:29:31 CEST 2011


Couldn't this be solved with an Iteratee approach? An Enumerator
produces values from your VM, an Enumeratee checks that only enough pass
(enough to disassemble 'this' instruction) and an Iteratee chews the
memory into the final value.
I'm writing this without the time to actually develop it, I'm sorry for
not providing any examples.

On Mon, 2011-05-09 at 18:41 +1000, Arlen Cuss wrote:
> Hi all,
> 
> I'm currently trying to write a very simple VM in order to learn and
> stretch my Haskell. I'm currently up against a problem.
> 
> I'm using an (IOUArray Int Word32) to represent the memory of a VM
> instance. This is all fine so far, but now I'm trying to write a
> 'disassemble' function that will disassemble an instruction starting
> from a given location in memory.
> 
> Ideally I could write a function that would lazily yield successive
> elements from memory, sort of like this:
> 
> > readVMFrom :: VM -> Address -> IO [Word32]
> > readVMFrom v f = do
> >   i <- readArray (memory v) f
> >   rest <- readVMFrom v (succ f)
> >   return $ i : readVMFrom v (succ f)
> 
> Of course, this isn't lazy, and so happily runs off the end of memory
> each time. (I could stop that, but that's not the point!) I'm not sure
> how to lazily construct a list in IO.
> 
> My next thought is to instead make a function to return an action that
> yields successive values of memory, given some start, i.e. something
> like:
> 
> > readVMFrom :: VM -> Address -> IO Word32
> 
> .. but I'm thinking I might have to do some StateT nonsense in order to
> actually keep track of which index we want to read next. (subtext: I
> don't know how to do that!)
> 
> So I then think that perhaps I can do this by having readVMFrom return
> an action which yields a) the next value, b) the address of the next
> value (so we know how much we ate), and c) an action to yield the next
> value and action and so on, so on. I managed that this way (WARNING,
> BEGINNER HASKELL CODE FOLLOWS):
> 
> > newtype RVFResult = RVFResult { getRVFResult :: (Word32, Address, IO
> RVFResult) }
> >
> > readVMFrom :: VM -> Address -> IO RVFResult
> > readVMFrom v f = do
> >   i <- readArray (memory v) f
> >   return $ RVFResult (i, succ f, readVMFrom v $ succ f)
> 
> A function can then take an argument of type RVFResult as an indication
> it wants 1..n sequential values from memory:
> 
> > disassemble :: RVFResult -> IO (Instruction, Address)
> > disassemble r = do
> >   let (i, p, a) = getRVFResult r
> >   case i of
> >     0x01 -> return (Push, p)
> >     0x02 -> return (Pop, p)
> >     0x03 -> return (Call, p)
> >     0x04 -> do
> >               r <- a
> >               let (v, p, a) = getRVFResult r
> >               return (Out v, p)
> 
> Here you can see how we consume an additional value by executing the
> returned action 'a'. It's damn ugly, and this almost looks like the
> place for a monad (possibly something involving StateT, though, I don't
> know!).
> 
> Ideally I'd manage a lazily constructed list -- somehow I feel that's
> most "Haskelly" -- but does anyone else have any ideas? I kinda fleshed
> this last solution out as I wrote this email, so it's kinda cruddy.
> 
> Cheers,
> 
> Arlen
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners





More information about the Beginners mailing list