[Haskell-beginners] Is there such a thing as a lazy monadic list?
Michael Snoyman
michael at snoyman.com
Tue May 10 17:42:17 CEST 2011
I've actually put the three parts together in a single chapter of the
Yesod book[1]. The information there should be up-to-date. I should
put a link to the chapter from the blog posts actually.
Michael
[1] http://www.yesodweb.com/book/enumerator
On Tue, May 10, 2011 at 5:31 PM, Elvio Toccalino
<elviotoccalino at gmail.com> wrote:
> Hi, Arlen.
> Last time I checked (which wasn't too long) the central packages were
> iteratee xor iteratee-mtl. I used a 'xor' there because they both
> implement the same functionality... their differences are beyond my
> knowledge, but check out their dependency list for a faint idea.
> What I ended up using, however, was the enumerator package. I did this
> following Michael Snoyman's blog post on the yesod blog[1] (three part
> post by the end of last year). I suggest you check it out, it was very
> useful for me (although it might have aged by now).
>
> Happy hacking!
>
> [1] http://www.yesodweb.com/blog/enumerators-tutorial-part-1
>
> On Tue, 2011-05-10 at 22:11 +1000, Arlen Cuss wrote:
>> Hi Elvio,
>>
>> > Couldn't this be solved with an Iteratee approach?
>>
>> Thanks for your reply! I'm now looking into this solution; is there a
>> standardised Enumerat{or,ee}/Iteratee library? Or is the situation still
>> as it was discussed in the following URL?
>> https://john-millikin.com/articles/understanding-iteratees/
>>
>> > 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.
>>
>> Cheers!
>>
>> > I'm writing this without the time to actually develop it, I'm sorry for
>> > not providing any examples.
>>
>> I'll come back when/if I manage it :)
>>
>> Arlen
>>
>> > 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
>> >
>> >
>> >
>> > _______________________________________________
>> > Beginners mailing list
>> > Beginners at haskell.org
>> > http://www.haskell.org/mailman/listinfo/beginners
>>
>>
>
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>
More information about the Beginners
mailing list