[Haskell-cafe] Re: Where do I put the seq?

Peter Verswyvelen bugfact at gmail.com
Wed Aug 19 16:20:58 EDT 2009


Well I really wrote this code as an exercise, and it was a good one. Now I
(or someone) needs to explain why it works.
But is this monad really useful? I mean it would be straightforward to write
this using the ST monad I guess?

Anyway, the reason why I want this pure code is that even with a console
based game, I don't want IO in it, since recording the input and replaying
it is vital to reproduce the actions the user did, and if things go wrong
(they always do), the log of all input can be used to restore the exact game
play. Of course you can do the same using imperative techniques and IO
redirection (which I did for my old games), but with this pure code you
don't have to worry about other places where IO could be used.

On Wed, Aug 19, 2009 at 10:06 PM, David Leimbach <leimy2k at gmail.com> wrote:

> Hmmm very interesting thinking on this.  Perhaps ByteStrings would be a
> good way to go for efficiency of composition.
> I'd love to see some profiling of all of this as part of the lesson at some
> point.  (Perhaps with vacuum visualization?)
>
> This thread has tackled 3 major tricky issue areas with Haskell so far:
>
> 1. Lazy IO and seq
> 2. Roll-your-own-Monad
> 3. Data growth profiling.
>
> It's been a good read anyway, and fun to play with the code.
>
> Dave
>
> On Wed, Aug 19, 2009 at 1:00 PM, Peter Verswyvelen <bugfact at gmail.com>wrote:
>
>> Wow, very nice cleanup! That's really a good way for me to learn, thanks.
>> Well, my intuition told me that strings and ++ wouldn't work, since what
>> we want is an infinite list of output strings, and using ++ would result in
>> (((s1++s2)++s3)++s4)++s5... which is highly inefficient and I think it would
>> keep the complete output text in memory. Using difference lists results in
>> right associative concatenation of s1++(s2++(s3++(s4++... which is efficient
>> and can be garbage collected nicely. At least that's what I guess. I really
>> would like to get a deeper understanding of all this but that will take lots
>> of time and study, but if I'm lucky I still have 20 to 40 years to go, so I
>> won't be bored :-)
>>
>>
>>
>>
>> On Wed, Aug 19, 2009 at 9:46 PM, David Leimbach <leimy2k at gmail.com>wrote:
>>
>>> Very cool!
>>> I am still wondering what the significance of the DList is with this
>>> though, or why it was needed to begin with.
>>>
>>> Dave
>>>
>>>
>>> On Wed, Aug 19, 2009 at 12:28 PM, Ryan Ingram <ryani.spam at gmail.com>wrote:
>>>
>>>> Added a new version (tested, works with infinite loops, no early output,
>>>> etc.)
>>>>
>>>> http://hpaste.org/fastcgi/hpaste.fcgi/view?id=8316#a8343
>>>>
>>>> I'll put up a short write-up after lunch.
>>>>
>>>>  -- ryan
>>>>
>>>> On Wed, Aug 19, 2009 at 11:28 AM, Peter Verswyvelen<bugfact at gmail.com>
>>>> wrote:
>>>> > The cleaned up code didn't seem to work for me, it printed everything
>>>> before
>>>> > asking input again.
>>>> > But I added a patch that looks like it supports looping, but I don't
>>>> > understand exactly what is going on :-)
>>>> > I added the "delay" function which makes appending to the output less
>>>> > strict.
>>>> > Note that in this version I add a delay to each right argument of >>=,
>>>> but
>>>> > one could also do it manually
>>>> > On Wed, Aug 19, 2009 at 7:37 PM, David Leimbach <leimy2k at gmail.com>
>>>> wrote:
>>>> >>
>>>> >> I've corrected it.  It still doesn't suffer looping.  :-)
>>>> >>
>>>> >> On Wed, Aug 19, 2009 at 10:31 AM, David Leimbach <leimy2k at gmail.com>
>>>> >> wrote:
>>>> >>>
>>>> >>> Doesn't seem to compile.
>>>> >>> I nearly never use case statements in my code, so I'm not really
>>>> sure
>>>> >>> what's going on.
>>>> >>> neat2.hs:14:39: parse error on input `='
>>>> >>> Dave
>>>> >>> On Wed, Aug 19, 2009 at 10:23 AM, Ryan Ingram <ryani.spam at gmail.com
>>>> >
>>>> >>> wrote:
>>>> >>>>
>>>> >>>> I posted a reply to your paste with a stricter version of S and
>>>> some
>>>> >>>> cleanup.
>>>> >>>>
>>>> >>>> Untested, though I believe it should work without "seq".
>>>> >>>>
>>>> >>>> "case" provides all the strictness you need, I think!
>>>> >>>>
>>>> >>>>  -- ryan
>>>> >>>>
>>>> >>>> On Wed, Aug 19, 2009 at 9:28 AM, Peter Verswyvelen<
>>>> bugfact at gmail.com>
>>>> >>>> wrote:
>>>> >>>> > Expect more bugs with this though :-) Just found out that looping
>>>> does
>>>> >>>> > not
>>>> >>>> > work, it hangs, e.g.
>>>> >>>> >
>>>> >>>> > test = do
>>>> >>>> >   out "Enter your first name:"
>>>> >>>> >   fstName <- inp
>>>> >>>> >   out "Enter your second name:"
>>>> >>>> >   sndName <- inp
>>>> >>>> >   out ("Welcome "++fstName++" "++sndName)
>>>> >>>> >   out "Goodbye!"
>>>> >>>> >   test
>>>> >>>> >
>>>> >>>> > Doesn't seem to work :-) Back to the drawing board.
>>>> >>>> >
>>>> >>>> > On Wed, Aug 19, 2009 at 5:55 PM, Peter Verswyvelen <
>>>> bugfact at gmail.com>
>>>> >>>> > wrote:
>>>> >>>> >>
>>>> >>>> >> Not at all, use it for whatever you want to :-)
>>>> >>>> >> I'm writing this code because I'm preparing to write a bunch of
>>>> >>>> >> tutorials
>>>> >>>> >> on FRP, and I first wanted to start with simple console based
>>>> FRP,
>>>> >>>> >> e.g.
>>>> >>>> >> making a little text adventure game, where the input/choices of
>>>> the
>>>> >>>> >> user
>>>> >>>> >> might be parsed ala parsec, using monadic style, applicative
>>>> style,
>>>> >>>> >> and
>>>> >>>> >> arrows, and then doing the same with FRP frameworks like Yampa,
>>>> >>>> >> Elera,
>>>> >>>> >> Reactive, etc...
>>>> >>>> >> After that I would start writing tutorials that use OpenGL,
>>>> making
>>>> >>>> >> some
>>>> >>>> >> very simple games, again with the above approaches, and ending
>>>> with a
>>>> >>>> >> conversion of a very old game of mine (Zarathrusta written in
>>>> >>>> >> assembler from
>>>> >>>> >> 1991, which was based on Thrust from 1986, converted by myself
>>>> in C++
>>>> >>>> >> to
>>>> >>>> >> PocketPC as G-Pod, and so I would like to make a version in
>>>> Haskell
>>>> >>>> >> that
>>>> >>>> >> runs on the iPhone :-)
>>>> >>>> >> This of course is a lot of work, and I would like to put this on
>>>> the
>>>> >>>> >> Haskell wiki or a blog or something, so others can contribute
>>>> and
>>>> >>>> >> comment. I
>>>> >>>> >> would like to show real examples that explain the shortcomings
>>>> of the
>>>> >>>> >> FRP
>>>> >>>> >> approaches, because now this is still a bit blurry to me.
>>>> >>>> >>
>>>> >>>> >> On Wed, Aug 19, 2009 at 5:43 PM, David Leimbach <
>>>> leimy2k at gmail.com>
>>>> >>>> >> wrote:
>>>> >>>> >>>
>>>> >>>> >>> This Monad you've created is quite excellent.  I was trying to
>>>> do
>>>> >>>> >>> something like this about a year ago, to make the input and
>>>> output
>>>> >>>> >>> handling
>>>> >>>> >>> of an interactive bowling score card work nicely.  I kept
>>>> running
>>>> >>>> >>> into
>>>> >>>> >>> issues, and did not believe that seq was going to do the trick.
>>>> >>>> >>>  Nice work!
>>>> >>>> >>> This is a very useful monad I think, it could be called
>>>> "Prompter"
>>>> >>>> >>> or
>>>> >>>> >>> something to that effect.
>>>> >>>> >>> Do you mind if I use it in some of my code?
>>>> >>>> >>> Dave
>>>> >>>> >>>
>>>> >>>> >>> On Wed, Aug 19, 2009 at 8:42 AM, Peter Verswyvelen
>>>> >>>> >>> <bugfact at gmail.com>
>>>> >>>> >>> wrote:
>>>> >>>> >>>>
>>>> >>>> >>>> LOL. Maybe we should have that coffee together ;-) at least
>>>> >>>> >>>> virtually!
>>>> >>>> >>>> On Wed, Aug 19, 2009 at 5:39 PM, David Leimbach <
>>>> leimy2k at gmail.com>
>>>> >>>> >>>> wrote:
>>>> >>>> >>>>>
>>>> >>>> >>>>> Argh... I too have been up too late :-).  I edited THE WRONG
>>>> FILE!
>>>> >>>> >>>>>  No
>>>> >>>> >>>>> wonder your change didn't take effect!  :-/
>>>> >>>> >>>>> Time for coffee I suppose.
>>>> >>>> >>>>>
>>>> >>>> >>>>> On Wed, Aug 19, 2009 at 8:38 AM, David Leimbach
>>>> >>>> >>>>> <leimy2k at gmail.com>
>>>> >>>> >>>>> wrote:
>>>> >>>> >>>>>>
>>>> >>>> >>>>>> This doesn't seem to be working for me interactively though
>>>> on a
>>>> >>>> >>>>>> Mac.
>>>> >>>> >>>>>>  I still get "Welcome" before I've entered text.
>>>> >>>> >>>>>>
>>>> >>>> >>>>>> On Wed, Aug 19, 2009 at 8:25 AM, Peter Verswyvelen
>>>> >>>> >>>>>> <bugfact at gmail.com>
>>>> >>>> >>>>>> wrote:
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>> I fixed it myself but it's really tricky :-)
>>>> >>>> >>>>>>> http://hpaste.org/fastcgi/hpaste.fcgi/view?id=8316#a8330
>>>> >>>> >>>>>>> The idea is, that when the input is requested, the output
>>>> that
>>>> >>>> >>>>>>> is
>>>> >>>> >>>>>>> then generated must be in sync with the input.
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>> inp = S $ \s i -> let r = (s `D.append` (i `seq` D.empty),
>>>> head
>>>> >>>> >>>>>>> i) in
>>>> >>>> >>>>>>> (tail i, r)
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>> I first had
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>> inp = S $ \s i -> let r = (i `seq` s, head i) in (tail i,
>>>> r)
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>> But that was too eager, since i syncs the input not with
>>>> the
>>>> >>>> >>>>>>> output,
>>>> >>>> >>>>>>> but with the function that will generate the output.
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>> Okay, now I can sleep again :-)
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>> On Wed, Aug 19, 2009 at 5:12 PM, Peter Verswyvelen
>>>> >>>> >>>>>>> <bugfact at gmail.com> wrote:
>>>> >>>> >>>>>>>>
>>>> >>>> >>>>>>>> Thanks, but that doesn't really matter in my example, my
>>>> code
>>>> >>>> >>>>>>>> is
>>>> >>>> >>>>>>>> just buggy, and I'm not sure why. For example if I change
>>>> my
>>>> >>>> >>>>>>>> test function
>>>> >>>> >>>>>>>> so that it outputs lines only, then it still prints
>>>> Welcome
>>>> >>>> >>>>>>>> first before
>>>> >>>> >>>>>>>> asking for input.
>>>> >>>> >>>>>>>> See
>>>> >>>> >>>>>>>> e.g.
>>>> http://hpaste.org/fastcgi/hpaste.fcgi/view?id=8316#a8328
>>>> >>>> >>>>>>>> On Wed, Aug 19, 2009 at 5:00 PM, David Leimbach
>>>> >>>> >>>>>>>> <leimy2k at gmail.com>
>>>> >>>> >>>>>>>> wrote:
>>>> >>>> >>>>>>>>>
>>>> >>>> >>>>>>>>> Try LineBuffering.
>>>> >>>> >>>>>>>>> I do linewise stuff with interact a lot.  You'll find
>>>> stuff
>>>> >>>> >>>>>>>>> like
>>>> >>>> >>>>>>>>> unlines . lines
>>>> >>>> >>>>>>>>> may help too.  In fact I just wrote a blog post about
>>>> this.
>>>> >>>> >>>>>>>>> http://leimy9.blogspot.com
>>>> >>>> >>>>>>>>> I'm trying to write some interactive code to automate
>>>> working
>>>> >>>> >>>>>>>>> with
>>>> >>>> >>>>>>>>> serial console controlled power strips, so I need to
>>>> either
>>>> >>>> >>>>>>>>> use Expect
>>>> >>>> >>>>>>>>> (yuck) or do my own thing.
>>>> >>>> >>>>>>>>> Dave
>>>> >>>> >>>>>>>>>
>>>> >>>> >>>>>>>>> On Wed, Aug 19, 2009 at 7:35 AM, Peter Verswyvelen
>>>> >>>> >>>>>>>>> <bugfact at gmail.com> wrote:
>>>> >>>> >>>>>>>>>>
>>>> >>>> >>>>>>>>>> Apparently this particular example happens to work on
>>>> Mac and
>>>> >>>> >>>>>>>>>> Linux because of different buffering (thanks Martijn for
>>>> the
>>>> >>>> >>>>>>>>>> help!)
>>>> >>>> >>>>>>>>>> To make sure we have no buffering at all, the main
>>>> function
>>>> >>>> >>>>>>>>>> should
>>>> >>>> >>>>>>>>>> be:
>>>> >>>> >>>>>>>>>>
>>>> >>>> >>>>>>>>>> main = do
>>>> >>>> >>>>>>>>>>   hSetBuffering stdout NoBuffering
>>>> >>>> >>>>>>>>>>   hSetBuffering stdin NoBuffering
>>>> >>>> >>>>>>>>>>   test
>>>> >>>> >>>>>>>>>>
>>>> >>>> >>>>>>>>>> Now I think it should also be incorrect on Unix systems.
>>>> >>>> >>>>>>>>>> I guess the way I'm concatenating the strings is not
>>>> correct,
>>>> >>>> >>>>>>>>>> not
>>>> >>>> >>>>>>>>>> sure.
>>>> >>>> >>>>>>>>>> I would like to use a graphical tool to show the graph
>>>> >>>> >>>>>>>>>> reduction
>>>> >>>> >>>>>>>>>> step by step, to get a better understanding of the
>>>> laziness &
>>>> >>>> >>>>>>>>>> strictness.
>>>> >>>> >>>>>>>>>> Does such a tool exist? I know people often say this is
>>>> not
>>>> >>>> >>>>>>>>>> usable because
>>>> >>>> >>>>>>>>>> the amount of information is too much, but I used to be
>>>> an
>>>> >>>> >>>>>>>>>> assembly language
>>>> >>>> >>>>>>>>>> programmer so I still would like to give it a try :-)
>>>> >>>> >>>>>>>>>>
>>>> >>>> >>>>>>>>>>
>>>> >>>> >>>>>>>>>> On Wed, Aug 19, 2009 at 1:07 PM, Peter Verswyvelen
>>>> >>>> >>>>>>>>>> <bugfact at gmail.com> wrote:
>>>> >>>> >>>>>>>>>>>
>>>> >>>> >>>>>>>>>>> In an attempt to get a deeper understanding of several
>>>> >>>> >>>>>>>>>>> monads
>>>> >>>> >>>>>>>>>>> (State, ST, IO, ...) I skimmed over some of the
>>>> research
>>>> >>>> >>>>>>>>>>> papers (but didn't
>>>> >>>> >>>>>>>>>>> understand all of it, I lack the required education)
>>>> and
>>>> >>>> >>>>>>>>>>> decided to write a
>>>> >>>> >>>>>>>>>>> little program myself without using any prefab monad
>>>> >>>> >>>>>>>>>>> instances that should
>>>> >>>> >>>>>>>>>>> mimic the following:
>>>> >>>> >>>>>>>>>>> main = do
>>>> >>>> >>>>>>>>>>>   putStrLn "Enter your name:"
>>>> >>>> >>>>>>>>>>>   x <- getLine
>>>> >>>> >>>>>>>>>>>   putStr "Welcome "
>>>> >>>> >>>>>>>>>>>   putStrLn x
>>>> >>>> >>>>>>>>>>>   putStrLn "Goodbye!"
>>>> >>>> >>>>>>>>>>> But instead of using IO, I wanted to make my own pure
>>>> monad
>>>> >>>> >>>>>>>>>>> that
>>>> >>>> >>>>>>>>>>> gets evaluated with interact, and does the same.
>>>> >>>> >>>>>>>>>>> However, I get the following output:
>>>> >>>> >>>>>>>>>>> Enter your name:
>>>> >>>> >>>>>>>>>>> Welcome ......
>>>> >>>> >>>>>>>>>>> So the Welcome is printed too soon.
>>>> >>>> >>>>>>>>>>> This is obvious since my monad is lazy, so I tried to
>>>> put a
>>>> >>>> >>>>>>>>>>> seq
>>>> >>>> >>>>>>>>>>> at some strategic places to get the same behavior as
>>>> IO. But
>>>> >>>> >>>>>>>>>>> I completely
>>>> >>>> >>>>>>>>>>> failed doing so, either the program doesn't print
>>>> anything
>>>> >>>> >>>>>>>>>>> and asks input
>>>> >>>> >>>>>>>>>>> first, or it still prints too much output.
>>>> >>>> >>>>>>>>>>> Of course I could just use ST, State, transformers,
>>>> etc, but
>>>> >>>> >>>>>>>>>>> this
>>>> >>>> >>>>>>>>>>> is purely an exercise I'm doing.
>>>> >>>> >>>>>>>>>>> So, I could re-read all papers and look in detail at
>>>> all the
>>>> >>>> >>>>>>>>>>> code, but maybe someone could help me out where to put
>>>> the
>>>> >>>> >>>>>>>>>>> seq or what to do
>>>> >>>> >>>>>>>>>>> :-)
>>>> >>>> >>>>>>>>>>> The code is
>>>> >>>> >>>>>>>>>>> at http://hpaste.org/fastcgi/hpaste.fcgi/view?id=8316
>>>> >>>> >>>>>>>>>>> Oh btw, the usage of DList here might not be needed;
>>>> >>>> >>>>>>>>>>> intuitively
>>>> >>>> >>>>>>>>>>> it felt like the correct thing to do, but when it comes
>>>> to
>>>> >>>> >>>>>>>>>>> Haskell, my
>>>> >>>> >>>>>>>>>>> intuition is usually wrong ;-)
>>>> >>>> >>>>>>>>>>> Thanks a lot,
>>>> >>>> >>>>>>>>>>> Peter Verswyvelen
>>>> >>>> >>>>>>>>>>
>>>> >>>> >>>>>>>>>>
>>>> >>>> >>>>>>>>>> _______________________________________________
>>>> >>>> >>>>>>>>>> Haskell-Cafe mailing list
>>>> >>>> >>>>>>>>>> Haskell-Cafe at haskell.org
>>>> >>>> >>>>>>>>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>> >>>> >>>>>>>>>>
>>>> >>>> >>>>>>>>>
>>>> >>>> >>>>>>>>
>>>> >>>> >>>>>>>
>>>> >>>> >>>>>>
>>>> >>>> >>>>>
>>>> >>>> >>>>
>>>> >>>> >>>
>>>> >>>> >>
>>>> >>>> >
>>>> >>>> >
>>>> >>>> > _______________________________________________
>>>> >>>> > Haskell-Cafe mailing list
>>>> >>>> > Haskell-Cafe at haskell.org
>>>> >>>> > http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>> >>>> >
>>>> >>>> >
>>>> >>>
>>>> >>
>>>> >
>>>> >
>>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20090819/0c71f0fe/attachment-0001.html


More information about the Haskell-Cafe mailing list